AmplNetworkWriter.java
/**
* Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
* Copyright (c) 2016-2017, 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.ampl.converter;
import com.powsybl.ampl.converter.util.AmplDatTableFormatter;
import com.powsybl.ampl.converter.version.AmplColumnsExporter;
import com.powsybl.commons.datasource.DataSource;
import com.powsybl.commons.extensions.Extendable;
import com.powsybl.commons.extensions.Extension;
import com.powsybl.commons.io.table.TableFormatter;
import com.powsybl.commons.util.StringToIntMapper;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.HvdcConverterStation.HvdcType;
import com.powsybl.iidm.network.util.ConnectedComponents;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Stream;
import static com.powsybl.ampl.converter.AmplConstants.DEFAULT_VARIANT_INDEX;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public class AmplNetworkWriter {
private static final Logger LOGGER = LoggerFactory.getLogger(AmplNetworkWriter.class);
private final Network network;
private final int variantIndex;
private final DataSource dataSource;
private final boolean append;
private final StringToIntMapper<AmplSubset> mapper; // id mapper
private final Map<String, List<AmplExtension>> extensionMap;
private final AmplExportConfig config;
private final AmplColumnsExporter columnsExporter;
private static class AmplExportContext {
private int otherCcNum = Integer.MAX_VALUE;
public final Set<String> busIdsToExport = new HashSet<>();
public final Set<String> voltageLevelIdsToExport = new HashSet<>();
public final Set<String> generatorIdsToExport = new HashSet<>();
public final Set<String> batteryIdsToExport = new HashSet<>();
public final Set<String> loadsToExport = new HashSet<>();
}
public AmplNetworkWriter(Network network, int variantIndex, DataSource dataSource, int faultNum, int actionNum,
boolean append, StringToIntMapper<AmplSubset> mapper, AmplExportConfig config) {
this.network = Objects.requireNonNull(network);
this.variantIndex = variantIndex;
this.dataSource = Objects.requireNonNull(dataSource);
this.append = append;
this.mapper = Objects.requireNonNull(mapper);
this.config = Objects.requireNonNull(config);
extensionMap = new HashMap<>();
this.columnsExporter = config.getVersion()
.getColumnsExporter()
.create(config, network, mapper, variantIndex, faultNum, actionNum);
}
public AmplNetworkWriter(Network network, DataSource dataSource, int faultNum, int actionNum,
boolean append, StringToIntMapper<AmplSubset> mapper, AmplExportConfig config) {
this(network, DEFAULT_VARIANT_INDEX, dataSource, faultNum, actionNum, append, mapper, config);
}
public AmplNetworkWriter(Network network, DataSource dataSource, StringToIntMapper<AmplSubset> mapper,
AmplExportConfig config) {
this(network, DEFAULT_VARIANT_INDEX, dataSource, 0, 0, false, mapper, config);
}
public AmplNetworkWriter(Network network, DataSource dataSource, AmplExportConfig config) {
this(network, DEFAULT_VARIANT_INDEX, dataSource, 0, 0, false, AmplUtil.createMapper(network), config);
}
private <I extends Identifiable<?>> Iterable<I> getSortedIdentifiables(Stream<I> equipments) {
return config.isExportSorted() ? equipments.sorted(Comparator.comparing(Identifiable::getId)).toList() : equipments.toList();
}
public static String getTableTitle(Network network, String tableName) {
return tableName + " (" + network.getId() + "/" + network.getVariantManager().getWorkingVariantId() + ")";
}
private static int getThreeWindingsTransformerMiddleBusComponentNum(AmplExportContext context, ThreeWindingsTransformer twt) {
Terminal t1 = twt.getLeg1().getTerminal();
Terminal t2 = twt.getLeg2().getTerminal();
Terminal t3 = twt.getLeg3().getTerminal();
Bus b1 = AmplUtil.getBus(t1);
Bus b2 = AmplUtil.getBus(t2);
Bus b3 = AmplUtil.getBus(t3);
int middleCcNum;
if (b1 != null) {
middleCcNum = ConnectedComponents.getCcNum(b1);
} else if (b2 != null) {
middleCcNum = ConnectedComponents.getCcNum(b2);
} else if (b3 != null) {
middleCcNum = ConnectedComponents.getCcNum(b3);
} else {
middleCcNum = context.otherCcNum--;
}
return middleCcNum;
}
private static int getDanglingLineMiddleBusComponentNum(AmplExportContext context, DanglingLine dl) {
Bus b = AmplUtil.getBus(dl.getTerminal());
int middleCcNum;
// if the connection bus of the dangling line is null or not in the main cc, the middle bus is
// obviously not in the main cc
if (b != null) {
middleCcNum = ConnectedComponents.getCcNum(b);
} else {
middleCcNum = context.otherCcNum--;
}
return middleCcNum;
}
private static int getTieLineMiddleBusComponentNum(AmplExportContext context, TieLine tieLine) {
Terminal t1 = tieLine.getDanglingLine1().getTerminal();
Terminal t2 = tieLine.getDanglingLine2().getTerminal();
Bus b1 = AmplUtil.getBus(t1);
Bus b2 = AmplUtil.getBus(t2);
int xNodeCcNum;
if (b1 != null) {
xNodeCcNum = ConnectedComponents.getCcNum(b1);
} else if (b2 != null) {
xNodeCcNum = ConnectedComponents.getCcNum(b2);
} else {
xNodeCcNum = context.otherCcNum--;
}
return xNodeCcNum;
}
private static boolean isBusExported(AmplExportContext context, String busId) {
return busId != null && context.busIdsToExport.contains(busId);
}
private String getTableTitle(String tableName) {
return getTableTitle(network, tableName);
}
private void writeSubstations() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_substations", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Substations"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getSubstationsColumns())) {
for (VoltageLevel vl : getSortedIdentifiables(network.getVoltageLevelStream())) {
columnsExporter.writeVoltageLevelToFormatter(formatter, vl);
addExtensions(mapper.getInt(AmplSubset.VOLTAGE_LEVEL, vl.getId()), vl);
}
// voltage level associated to 3 windings transformers middle bus
for (ThreeWindingsTransformer twt : getSortedIdentifiables(network.getThreeWindingsTransformerStream())) {
columnsExporter.writeThreeWindingsTransformerVoltageLevelToFormatter(formatter, twt);
addExtensions(mapper.getInt(AmplSubset.VOLTAGE_LEVEL,
AmplUtil.getThreeWindingsTransformerMiddleVoltageLevelId(twt)), twt);
}
// voltage level associated to dangling lines middle bus
for (DanglingLine dl : getSortedIdentifiables(network.getDanglingLineStream(DanglingLineFilter.UNPAIRED))) {
columnsExporter.writeDanglingLineVoltageLevelToFormatter(formatter, dl);
addExtensions(mapper.getInt(AmplSubset.VOLTAGE_LEVEL, AmplUtil.getDanglingLineMiddleVoltageLevelId(dl)),
dl);
}
if (config.isExportXNodes()) {
for (TieLine tieLine : getSortedIdentifiables(network.getTieLineStream())) {
columnsExporter.writeTieLineVoltageLevelToFormatter(formatter, tieLine);
addExtensions(mapper.getInt(AmplSubset.VOLTAGE_LEVEL, AmplUtil.getXnodeVoltageLevelId(tieLine)),
tieLine);
}
}
}
}
private boolean isOnlyMainCc() {
return switch (config.getExportScope()) {
case ONLY_MAIN_CC, ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS, ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS_AND_ALL_LOADS ->
true;
case ALL -> false;
};
}
private boolean connectedComponentToExport(int numCC) {
return !(isOnlyMainCc() && numCC != ComponentConstants.MAIN_NUM);
}
private void writeBuses(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_buses", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Buses"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getBusesColumns())) {
writeBuses(context, formatter);
writeThreeWindingsTransformerMiddleBuses(context, formatter);
writeDanglingLineMiddleBuses(context, formatter);
if (config.isExportXNodes()) {
writeTieLineMiddleBuses(context, formatter);
}
}
}
private void writeBuses(AmplExportContext context, TableFormatter formatter) throws IOException {
for (Bus b : AmplUtil.getBuses(network)) {
int ccNum = ConnectedComponents.getCcNum(b);
if (connectedComponentToExport(ccNum)) {
context.busIdsToExport.add(b.getId());
columnsExporter.writeBusesColumnsToFormatter(formatter, b);
addExtensions(mapper.getInt(AmplSubset.BUS, b.getId()), b);
}
}
}
private <E> void addExtensions(int extendedNum, Extendable<E> extendable) {
for (Extension<E> ext : extendable.getExtensions()) {
List<AmplExtension> extList = extensionMap.computeIfAbsent(ext.getName(), k -> new ArrayList<>());
extList.add(new AmplExtension(extendedNum, extendable, ext));
extensionMap.put(ext.getName(), extList);
}
}
private void addNetworkExtensions() {
int networkNum = mapper.getInt(AmplSubset.NETWORK, network.getId());
addExtensions(networkNum, network);
}
private void exportExtensions() throws IOException {
for (Entry<String, List<AmplExtension>> entry : extensionMap.entrySet()) {
AmplExtensionWriter extWriter = AmplExtensionWriters.getWriter(entry.getKey());
if (extWriter != null) {
extWriter.write(entry.getValue(), network, variantIndex, mapper, dataSource, append, config);
}
}
}
private void writeThreeWindingsTransformerMiddleBuses(AmplExportContext context, TableFormatter formatter) throws IOException {
for (ThreeWindingsTransformer twt : getSortedIdentifiables(network.getThreeWindingsTransformerStream())) {
int middleCcNum = getThreeWindingsTransformerMiddleBusComponentNum(context, twt);
if (connectedComponentToExport(middleCcNum)) {
String middleBusId = AmplUtil.getThreeWindingsTransformerMiddleBusId(twt);
context.busIdsToExport.add(middleBusId);
columnsExporter.writeThreeWindingsTranformersMiddleBusesColumnsToFormatter(formatter, twt, middleCcNum);
}
}
}
private void writeDanglingLineMiddleBuses(AmplExportContext context, TableFormatter formatter) throws IOException {
for (DanglingLine dl : getSortedIdentifiables(network.getDanglingLineStream(DanglingLineFilter.UNPAIRED))) {
int middleCcNum = getDanglingLineMiddleBusComponentNum(context, dl);
if (connectedComponentToExport(middleCcNum)) {
context.busIdsToExport.add(AmplUtil.getDanglingLineMiddleBusId(dl));
columnsExporter.writeDanglingLineMiddleBusesToFormatter(formatter, dl, middleCcNum);
}
}
}
private void writeTieLineMiddleBuses(AmplExportContext context, TableFormatter formatter) throws IOException {
for (TieLine tieLine : getSortedIdentifiables(network.getTieLineStream())) {
int xNodeCcNum = getTieLineMiddleBusComponentNum(context, tieLine);
if (connectedComponentToExport(xNodeCcNum)) {
columnsExporter.writeTieLineMiddleBusesToFormatter(formatter, tieLine, xNodeCcNum);
}
}
}
private void writeBranches(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_branches", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Branches"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getBranchesColumns()
)) {
writeLines(context, formatter);
writeTieLines(context, formatter);
writeTwoWindingsTransformers(context, formatter);
writeThreeWindingsTransformers(context, formatter);
writeDanglingLines(context, formatter);
}
}
private void writeLines(AmplExportContext context, TableFormatter formatter) throws IOException {
for (Line l : getSortedIdentifiables(network.getLineStream())) {
Terminal t1 = l.getTerminal1();
Terminal t2 = l.getTerminal2();
if (addVoltageLevelIdsToExport(context, t1, t2, l.getId())) {
columnsExporter.writeLinesToFormatter(formatter, l);
addExtensions(mapper.getInt(AmplSubset.BRANCH, l.getId()), l);
}
}
}
private boolean addVoltageLevelIdsToExport(AmplExportContext context, Terminal t1, Terminal t2, String id) {
Bus bus1 = AmplUtil.getBus(t1);
Bus bus2 = AmplUtil.getBus(t2);
if (bus2 != null && bus1 == bus2) {
LOGGER.warn("Skipping line '{}' connected to the same bus at both sides", id);
return false;
}
String bus1Id = AmplUtil.getBusId(bus1);
String bus2Id = AmplUtil.getBusId(bus2);
if (isOnlyMainCc() && !(isBusExported(context, bus1Id) || isBusExported(context, bus2Id))) {
return false;
}
context.voltageLevelIdsToExport.add(t1.getVoltageLevel().getId());
context.voltageLevelIdsToExport.add(t2.getVoltageLevel().getId());
return true;
}
private void writeTieLines(AmplExportContext context, TableFormatter formatter) throws IOException {
for (TieLine l : getSortedIdentifiables(network.getTieLineStream())) {
Terminal t1 = l.getDanglingLine1().getTerminal();
Terminal t2 = l.getDanglingLine2().getTerminal();
if (addVoltageLevelIdsToExport(context, t1, t2, l.getId())) {
columnsExporter.writeTieLineToFormatter(formatter, l);
addExtensions(mapper.getInt(AmplSubset.BRANCH, l.getId()), l);
}
}
}
private void writeTwoWindingsTransformers(AmplExportContext context, TableFormatter formatter) throws IOException {
for (TwoWindingsTransformer twt : getSortedIdentifiables(network.getTwoWindingsTransformerStream())) {
Terminal t1 = twt.getTerminal1();
Terminal t2 = twt.getTerminal2();
Bus bus1 = AmplUtil.getBus(t1);
Bus bus2 = AmplUtil.getBus(t2);
if (bus1 != null && bus1 == bus2) {
LOGGER.warn("Skipping transformer '{}' connected to the same bus at both sides", twt.getId());
} else if (!isOnlyMainCc() || isBusExported(context, AmplUtil.getBusId(bus1)) || isBusExported(context, AmplUtil.getBusId(bus2))) {
context.voltageLevelIdsToExport.add(t1.getVoltageLevel().getId());
context.voltageLevelIdsToExport.add(t2.getVoltageLevel().getId());
columnsExporter.writeTwoWindingsTranformerToFormatter(formatter, twt);
addExtensions(mapper.getInt(AmplSubset.BRANCH, twt.getId()), twt);
}
}
}
private void writeThreeWindingsTransformers(AmplExportContext context, TableFormatter formatter) throws IOException {
for (ThreeWindingsTransformer twt : getSortedIdentifiables(network.getThreeWindingsTransformerStream())) {
Terminal t1 = twt.getLeg1().getTerminal();
Terminal t2 = twt.getLeg2().getTerminal();
Terminal t3 = twt.getLeg3().getTerminal();
Bus bus1 = AmplUtil.getBus(t1);
Bus bus2 = AmplUtil.getBus(t2);
Bus bus3 = AmplUtil.getBus(t3);
// TODO could be connected to the same bus at 2 or 3 ends ?
VoltageLevel vl1 = t1.getVoltageLevel();
VoltageLevel vl2 = t2.getVoltageLevel();
VoltageLevel vl3 = t3.getVoltageLevel();
context.voltageLevelIdsToExport.add(vl1.getId());
context.voltageLevelIdsToExport.add(vl2.getId());
context.voltageLevelIdsToExport.add(vl3.getId());
String id1 = twt.getId() + AmplConstants.LEG1_SUFFIX;
String id2 = twt.getId() + AmplConstants.LEG2_SUFFIX;
String id3 = twt.getId() + AmplConstants.LEG3_SUFFIX;
int num1 = mapper.getInt(AmplSubset.BRANCH, id1);
int num2 = mapper.getInt(AmplSubset.BRANCH, id2);
int num3 = mapper.getInt(AmplSubset.BRANCH, id3);
String bus1Id = AmplUtil.getBusId(bus1);
String bus2Id = AmplUtil.getBusId(bus2);
String bus3Id = AmplUtil.getBusId(bus3);
int middleVlNum = mapper.getInt(AmplSubset.VOLTAGE_LEVEL,
AmplUtil.getThreeWindingsTransformerMiddleVoltageLevelId(twt));
String middleBusId = AmplUtil.getThreeWindingsTransformerMiddleBusId(twt);
int middleBusNum = mapper.getInt(AmplSubset.BUS, middleBusId);
if (!isOnlyMainCc() || isBusExported(context, middleBusId) || isBusExported(context, bus1Id)) {
columnsExporter.writeThreeWindingsTransformerLegToFormatter(formatter, twt, middleBusNum, middleVlNum,
ThreeSides.ONE);
addExtensions(num1, twt);
}
if (!isOnlyMainCc() || isBusExported(context, middleBusId) || isBusExported(context, bus2Id)) {
columnsExporter.writeThreeWindingsTransformerLegToFormatter(formatter, twt, middleBusNum, middleVlNum,
ThreeSides.TWO);
addExtensions(num2, twt);
}
if (!isOnlyMainCc() || isBusExported(context, middleBusId) || isBusExported(context, bus3Id)) {
columnsExporter.writeThreeWindingsTransformerLegToFormatter(formatter, twt, middleBusNum, middleVlNum,
ThreeSides.THREE);
addExtensions(num3, twt);
}
}
}
private void writeDanglingLines(AmplExportContext context, TableFormatter formatter) throws IOException {
for (DanglingLine dl : getSortedIdentifiables(network.getDanglingLineStream(DanglingLineFilter.UNPAIRED))) {
Terminal t = dl.getTerminal();
Bus bus1 = AmplUtil.getBus(t);
String bus1Id = AmplUtil.getBusId(bus1);
String middleBusId = AmplUtil.getDanglingLineMiddleBusId(dl);
if (!isOnlyMainCc() || isBusExported(context, bus1Id) || isBusExported(context, middleBusId)) {
VoltageLevel vl = t.getVoltageLevel();
String middleVlId = AmplUtil.getDanglingLineMiddleVoltageLevelId(dl);
context.voltageLevelIdsToExport.add(vl.getId());
context.voltageLevelIdsToExport.add(middleVlId);
columnsExporter.writeDanglingLineToFormatter(formatter, dl);
addExtensions(mapper.getInt(AmplSubset.BRANCH, dl.getId()), dl);
}
}
}
private void writeTapChangerTable() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_tct", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Tap changer table"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getTapChangerTableColumns())) {
writeTwoWindingsTransformerTapChangerTable(formatter);
writeThreeWindingsTransformerTapChangerTable(formatter);
}
}
private void writeTwoWindingsTransformerTapChangerTable(TableFormatter formatter) throws IOException {
for (TwoWindingsTransformer twt : getSortedIdentifiables(network.getTwoWindingsTransformerStream())) {
columnsExporter.writeTwoWindingsTransformerTapChangerTableToFormatter(formatter, twt);
}
}
private void writeThreeWindingsTransformerTapChangerTable(TableFormatter formatter) throws IOException {
for (ThreeWindingsTransformer twt : getSortedIdentifiables(network.getThreeWindingsTransformerStream())) {
columnsExporter.writeThreeWindingsTransformerTapChangerTableToFormatter(formatter, twt);
}
}
private void writeRatioTapChangers() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_rtc", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Ratio tap changers"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getRtcColumns())) {
columnsExporter.writeRtcToFormatter(formatter);
}
}
private void writePhaseTapChangers() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_ptc", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Phase tap changers"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getPtcColumns())) {
columnsExporter.writePtcToFormatter(formatter);
}
}
private boolean exportLoad(AmplExportContext context, String busId) {
return switch (config.getExportScope()) {
case ALL, ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS_AND_ALL_LOADS -> true;
case ONLY_MAIN_CC, ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS -> isBusExported(context, busId);
};
}
private void writeLoads(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_loads", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Loads"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getLoadsColumns())) {
List<String> skipped = new ArrayList<>();
for (Load l : getSortedIdentifiables(network.getLoadStream())) {
Terminal t = l.getTerminal();
Bus bus = AmplUtil.getBus(t);
String busId = null;
if (bus != null) {
busId = bus.getId();
}
if (!exportLoad(context, busId)) {
skipped.add(l.getId());
} else {
context.loadsToExport.add(l.getId());
columnsExporter.writeLoadtoFormatter(formatter, l);
addExtensions(mapper.getInt(AmplSubset.LOAD, l.getId()), l);
}
}
for (DanglingLine dl : getSortedIdentifiables(network.getDanglingLineStream(DanglingLineFilter.UNPAIRED))) {
String middleBusId = AmplUtil.getDanglingLineMiddleBusId(dl);
if (!exportLoad(context, middleBusId)) {
skipped.add(dl.getId());
} else {
columnsExporter.writeDanglingLineLoadToFormatter(formatter, dl);
}
}
if (!skipped.isEmpty()) {
LOGGER.trace("Skip loads {} because not connected and not connectable", skipped);
}
}
}
private boolean exportGeneratorOrShunt(AmplExportContext context, String busId, String conBusId) {
return switch (config.getExportScope()) {
case ALL -> true;
case ONLY_MAIN_CC -> isBusExported(context, busId);
case ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS, ONLY_MAIN_CC_AND_CONNECTABLE_GENERATORS_AND_SHUNTS_AND_ALL_LOADS ->
isBusExported(context, conBusId);
};
}
private void writeShunts(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_shunts", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Shunts"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getShuntsColumns())) {
List<String> skipped = new ArrayList<>();
for (ShuntCompensator sc : getSortedIdentifiables(network.getShuntCompensatorStream())) {
Terminal t = sc.getTerminal();
Bus bus = AmplUtil.getBus(t);
String busId = null;
if (bus != null) {
busId = bus.getId();
}
// take connectable bus if exists
String conBusId = null;
Bus conBus = AmplUtil.getConnectableBus(t);
if (conBus != null) {
conBusId = conBus.getId();
}
if (!exportGeneratorOrShunt(context, busId, conBusId)) {
skipped.add(sc.getId());
} else {
columnsExporter.writeShuntCompensatorToFormatter(formatter, sc);
addExtensions(mapper.getInt(AmplSubset.SHUNT, sc.getId()), sc);
}
}
if (!skipped.isEmpty()) {
LOGGER.trace("Skip shunts {} because not connected and not connectable", skipped);
}
}
}
private void writeStaticVarCompensators() throws IOException {
try (Writer writer = new OutputStreamWriter(
dataSource.newOutputStream("_network_static_var_compensators", "txt", append), StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Static VAR compensators"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getStaticVarCompensatorColumns())) {
List<String> skipped = new ArrayList<>();
for (StaticVarCompensator svc : getSortedIdentifiables(network.getStaticVarCompensatorStream())) {
columnsExporter.writeStaticVarCompensatorToFormatter(formatter, svc);
addExtensions(mapper.getInt(AmplSubset.STATIC_VAR_COMPENSATOR, svc.getId()), svc);
}
if (!skipped.isEmpty()) {
LOGGER.trace("Skip static VAR compensators {} because not connected and not connectable", skipped);
}
}
}
private void writeGenerators(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_generators", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Generators"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getGeneratorsColumns())) {
List<String> skipped = new ArrayList<>();
for (Generator g : getSortedIdentifiables(network.getGeneratorStream())) {
Terminal t = g.getTerminal();
Bus bus = AmplUtil.getBus(t);
String busId = null;
if (bus != null) {
busId = bus.getId();
}
String conBusId = null;
// take connectable bus if exists
Bus conBus = AmplUtil.getConnectableBus(t);
if (conBus != null) {
conBusId = conBus.getId();
}
if (!exportGeneratorOrShunt(context, busId, conBusId)) {
skipped.add(g.getId());
} else {
context.generatorIdsToExport.add(g.getId());
columnsExporter.writeGeneratorToFormatter(formatter, g);
addExtensions(mapper.getInt(AmplSubset.GENERATOR, g.getId()), g);
}
}
if (!skipped.isEmpty()) {
LOGGER.trace("Skip generators {} because not connected and not connectable", skipped);
}
}
}
private void writeBatteries(AmplExportContext context) throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_batteries", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Batteries"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getBatteriesColumns())) {
List<String> skipped = new ArrayList<>();
for (Battery b : getSortedIdentifiables(network.getBatteryStream())) {
Terminal t = b.getTerminal();
Bus bus = AmplUtil.getBus(t);
String busId = null;
if (bus != null) {
busId = bus.getId();
}
// take connectable bus if exists
if (!isBusExported(context, busId)) {
skipped.add(b.getId());
} else {
context.batteryIdsToExport.add(b.getId());
columnsExporter.writeBatteryToFormatter(formatter, b);
addExtensions(mapper.getInt(AmplSubset.BATTERY, b.getId()), b);
}
}
if (!skipped.isEmpty()) {
LOGGER.trace("Skip batteries {} because not connected and not connectable", skipped);
}
}
}
private void writeCurrentLimits() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_limits", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("Temporary current limits"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getCurrentLimitsColumns())) {
columnsExporter.writeCurrentLimits(formatter);
}
}
private void writeHvdcLines() throws IOException {
try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_hvdc", "txt", append),
StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("HVDC lines"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getHvdcLinesColumns())) {
for (HvdcLine hvdcLine : getSortedIdentifiables(network.getHvdcLineStream())) {
columnsExporter.writeHvdcToFormatter(formatter, hvdcLine);
addExtensions(mapper.getInt(AmplSubset.HVDC_LINE, hvdcLine.getId()), hvdcLine);
}
}
}
private void writeLccConverterStations() throws IOException {
try (Writer writer = new OutputStreamWriter(
dataSource.newOutputStream("_network_lcc_converter_stations", "txt", append), StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("LCC Converter Stations"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getLccConverterStationsColumns())) {
for (HvdcConverterStation<?> hvdcStation : getSortedIdentifiables(network.getHvdcConverterStationStream())) {
if (hvdcStation.getHvdcType().equals(HvdcType.LCC)) {
LccConverterStation lccStation = (LccConverterStation) hvdcStation;
columnsExporter.writeLccConverterStationToFormatter(formatter, lccStation);
addExtensions(mapper.getInt(AmplSubset.LCC_CONVERTER_STATION, lccStation.getId()), lccStation);
}
}
}
}
private void writeVscConverterStations() throws IOException {
try (Writer writer = new OutputStreamWriter(
dataSource.newOutputStream("_network_vsc_converter_stations", "txt", append), StandardCharsets.UTF_8);
TableFormatter formatter = new AmplDatTableFormatter(writer,
getTableTitle("VSC Converter Stations"),
AmplConstants.INVALID_FLOAT_VALUE,
!append,
AmplConstants.LOCALE,
columnsExporter.getVscConverterStationsColumns())) {
for (HvdcConverterStation<?> hvdcStation : getSortedIdentifiables(network.getHvdcConverterStationStream())) {
if (hvdcStation.getHvdcType().equals(HvdcType.VSC)) {
VscConverterStation vscStation = (VscConverterStation) hvdcStation;
columnsExporter.writeVscConverterStationToFormatter(formatter, vscStation);
addExtensions(mapper.getInt(AmplSubset.VSC_CONVERTER_STATION, vscStation.getId()), vscStation);
}
}
}
}
public void write() throws IOException {
write(new AmplExportContext());
}
public void write(AmplExportContext context) throws IOException {
extensionMap.clear();
writeBuses(context);
writeTapChangerTable();
writeRatioTapChangers();
writePhaseTapChangers();
writeBranches(context);
writeCurrentLimits();
writeGenerators(context);
writeBatteries(context);
writeLoads(context);
writeShunts(context);
writeStaticVarCompensators();
writeSubstations();
writeVscConverterStations();
writeLccConverterStations();
writeHvdcLines();
writeHeaders();
addNetworkExtensions();
exportExtensions();
}
private void writeHeaders() throws IOException {
try (Writer writer = new OutputStreamWriter(
dataSource.newOutputStream("_headers", "txt", append), StandardCharsets.UTF_8)
) {
writer.write("version " + config.getVersion().getExporterId() + "\n");
}
}
}