diff --git a/.travis.yml b/.travis.yml index b8c30e15..b1f16ba6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: script: - cd ${TRAVIS_BUILD_DIR} -- mvn clean test jacoco:report coveralls:report +- mvn clean verify jacoco:report coveralls:report addons: ssh_known_hosts: sftp.dc0.gpaas.net diff --git a/ampl-export/src/main/java/eu/itesla_project/iidm/export/ampl/AmplNetworkWriter.java b/ampl-export/src/main/java/eu/itesla_project/iidm/export/ampl/AmplNetworkWriter.java index e7a71d7f..852df004 100644 --- a/ampl-export/src/main/java/eu/itesla_project/iidm/export/ampl/AmplNetworkWriter.java +++ b/ampl-export/src/main/java/eu/itesla_project/iidm/export/ampl/AmplNetworkWriter.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashSet; @@ -111,23 +112,24 @@ private static String getDanglingLineMiddleVoltageLevelId(DanglingLine dl) { } private void writeSubstations(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_substations", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Substations"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("horizon"), - new Column("reference date distance (minutes)"), - new Column("nomV (KV)"), - new Column("minV (pu)"), - new Column("maxV (pu)"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("country"), - new Column("id"), - new Column("description"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_substations", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Substations"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("horizon"), + new Column("reference date distance (minutes)"), + new Column("nomV (KV)"), + new Column("minV (pu)"), + new Column("maxV (pu)"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("country"), + new Column("id"), + new Column("description"))) { for (VoltageLevel vl : network.getVoltageLevels()) { // if (!context.voltageLevelIdsToExport.contains(vl.getId())) { // continue; @@ -233,22 +235,23 @@ private boolean isOnlyMainCc() { } private void writeBuses(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_buses", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Buses"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("substation"), - new Column("cc"), - new Column("v (pu)"), - new Column("theta (rad)"), - new Column("p (MW)"), - new Column("q (MVar)"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_buses", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Buses"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("substation"), + new Column("cc"), + new Column("v (pu)"), + new Column("theta (rad)"), + new Column("p (MW)"), + new Column("q (MVar)"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"))) { for (Bus b : AmplUtil.getBuses(network)) { int ccNum = ConnectedComponents.getCcNum(b); // skip buses not in the main connected component @@ -400,38 +403,39 @@ private static boolean isBusExported(AmplExportContext context, String busId) { } private void writeBranches(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_branches", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Branches"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("bus1"), - new Column("bus2"), - new Column("3wt num"), - new Column("sub.1"), - new Column("sub.2"), - new Column("r (pu)"), - new Column("x (pu)"), - new Column("g1 (pu)"), - new Column("g2 (pu)"), - new Column("b1 (pu)"), - new Column("b2 (pu)"), - new Column("cst ratio (pu)"), - new Column("ratio tc"), - new Column("phase tc"), - new Column("p1 (MW)"), - new Column("p2 (MW)"), - new Column("q1 (MVar)"), - new Column("q2 (MVar)"), - new Column("patl1 (A)"), - new Column("patl2 (A)"), - new Column("merged"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"), - new Column("description"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_branches", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Branches"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("bus1"), + new Column("bus2"), + new Column("3wt num"), + new Column("sub.1"), + new Column("sub.2"), + new Column("r (pu)"), + new Column("x (pu)"), + new Column("g1 (pu)"), + new Column("g2 (pu)"), + new Column("b1 (pu)"), + new Column("b2 (pu)"), + new Column("cst ratio (pu)"), + new Column("ratio tc"), + new Column("phase tc"), + new Column("p1 (MW)"), + new Column("p2 (MW)"), + new Column("q1 (MVar)"), + new Column("q2 (MVar)"), + new Column("patl1 (A)"), + new Column("patl2 (A)"), + new Column("merged"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"), + new Column("description"))) { for (Line l : network.getLines()) { Terminal t1 = l.getTerminal1(); Terminal t2 = l.getTerminal2(); @@ -850,19 +854,20 @@ private void writeBranches(AmplExportContext context) throws IOException { } private void writeTapChangerTable() throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_tct", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Tap changer table"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("tap"), - new Column("var ratio"), - new Column("x (pu)"), - new Column("angle (rad)"), - new Column("fault"), - new Column(config.getActionType().getLabel()))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_tct", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Tap changer table"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("tap"), + new Column("var ratio"), + new Column("x (pu)"), + new Column("angle (rad)"), + new Column("fault"), + new Column(config.getActionType().getLabel()))) { for (TwoWindingsTransformer twt : network.getTwoWindingsTransformers()) { Terminal t2 = twt.getTerminal2(); float vb2 = t2.getVoltageLevel().getNominalV(); @@ -972,13 +977,14 @@ private void writeRatioTapChangers() throws IOException { columns.add(new Column("fault")); columns.add(new Column(config.getActionType().getLabel())); columns.add(new Column("id")); - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_rtc", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Ratio tap changers"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - columns.toArray(new Column[columns.size()]))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_rtc", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Ratio tap changers"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + columns.toArray(new Column[columns.size()]))) { for (TwoWindingsTransformer twt : network.getTwoWindingsTransformers()) { RatioTapChanger rtc = twt.getRatioTapChanger(); if (rtc != null) { @@ -1005,18 +1011,19 @@ private void writeRatioTapChangers() throws IOException { } private void writePhaseTapChangers() throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_ptc", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Phase tap changers"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("tap"), - new Column("table"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_ptc", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Phase tap changers"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("tap"), + new Column("table"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"))) { for (TwoWindingsTransformer twt : network.getTwoWindingsTransformers()) { PhaseTapChanger ptc = twt.getPhaseTapChanger(); if (ptc != null) { @@ -1049,21 +1056,22 @@ private boolean exportLoad(AmplExportContext context, String busId) { } private void writeLoads(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_loads", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Loads"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("bus"), - new Column("substation"), - new Column("p (MW)"), - new Column("q (MVar)"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"), - new Column("description"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_loads", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Loads"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("bus"), + new Column("substation"), + new Column("p (MW)"), + new Column("q (MVar)"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"), + new Column("description"))) { List skipped = new ArrayList<>(); for (Load l : network.getLoads()) { Terminal t = l.getTerminal(); @@ -1134,24 +1142,25 @@ private boolean exportGeneratorOrShunt(AmplExportContext context, String busId, } private void writeShunts(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_shunts", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Shunts"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("bus"), - new Column("con. bus"), - new Column("substation"), - new Column("minB (pu)"), - new Column("maxB (pu)"), - new Column("inter. points"), - new Column("b (pu)"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"), - new Column("description"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_shunts", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Shunts"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("bus"), + new Column("con. bus"), + new Column("substation"), + new Column("minB (pu)"), + new Column("maxB (pu)"), + new Column("inter. points"), + new Column("b (pu)"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"), + new Column("description"))) { List skipped = new ArrayList<>(); for (ShuntCompensator sc : network.getShunts()) { Terminal t = sc.getTerminal(); @@ -1205,16 +1214,17 @@ private void writeShunts(AmplExportContext context) throws IOException { } private void writeStaticVarCompensators(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_static_var_compensators", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Static VAR compensators"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"))) { + 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"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"))) { List skipped = new ArrayList<>(); for (StaticVarCompensator svc : network.getStaticVarCompensators()) { // FIXME @@ -1232,30 +1242,31 @@ private void writeStaticVarCompensators(AmplExportContext context) throws IOExce } private void writeGenerators(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_generators", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Generators"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("bus"), - new Column("con. bus"), - new Column("substation"), - new Column("minP (MW)"), - new Column("maxP (MW)"), - new Column("minQmaxP (MVar)"), - new Column("minQminP (MVar)"), - new Column("maxQmaxP (MVar)"), - new Column("maxQminP (MVar)"), - new Column("v regul."), - new Column("targetV (pu)"), - new Column("targetP (MW)"), - new Column("targetQ (MVar)"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"), - new Column("description"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_generators", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Generators"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("bus"), + new Column("con. bus"), + new Column("substation"), + new Column("minP (MW)"), + new Column("maxP (MW)"), + new Column("minQmaxP (MVar)"), + new Column("minQminP (MVar)"), + new Column("maxQmaxP (MVar)"), + new Column("maxQminP (MVar)"), + new Column("v regul."), + new Column("targetV (pu)"), + new Column("targetP (MW)"), + new Column("targetQ (MVar)"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"), + new Column("description"))) { List skipped = new ArrayList<>(); for (Generator g : network.getGenerators()) { Terminal t = g.getTerminal(); @@ -1326,19 +1337,20 @@ private void writeTemporaryCurrentLimits(CurrentLimits limits, TableFormatter fo } private void writeTemporaryCurrentLimits() throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_limits", "txt", append), StandardCharsets.UTF_8), - getTableTitle("Temporary current limits"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("branch"), - new Column("side"), - new Column("limit (A)"), - new Column("accept. duration (s)"), - new Column("fault"), - new Column(config.getActionType().getLabel()))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_limits", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("Temporary current limits"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("branch"), + new Column("side"), + new Column("limit (A)"), + new Column("accept. duration (s)"), + new Column("fault"), + new Column(config.getActionType().getLabel()))) { for (Line l : network.getLines()) { String branchId = l.getId(); if (l.getCurrentLimits1() != null) { @@ -1400,16 +1412,17 @@ public void write(AmplExportContext context) throws IOException { } private void writeHVDCLines(AmplExportContext context) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream("_network_hvdc", "txt", append), StandardCharsets.UTF_8), - getTableTitle("HVDC lines"), - INVALID_FLOAT_VALUE, - !append, - LOCALE, - new Column("num"), - new Column("fault"), - new Column(config.getActionType().getLabel()), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream("_network_hvdc", "txt", append), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + getTableTitle("HVDC lines"), + INVALID_FLOAT_VALUE, + !append, + LOCALE, + new Column("num"), + new Column("fault"), + new Column(config.getActionType().getLabel()), + new Column("id"))) { List skipped = new ArrayList<>(); for (HvdcLine hvdcLine : network.getHvdcLines()) { // FIXME diff --git a/eurostag-step-up-transformer/pom.xml b/eurostag-step-up-transformer/pom.xml index 90cc8600..06adc930 100644 --- a/eurostag-step-up-transformer/pom.xml +++ b/eurostag-step-up-transformer/pom.xml @@ -62,6 +62,11 @@ + + com.google.jimfs + jimfs + test + com.powsybl powsybl-iidm-impl diff --git a/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDB.java b/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDB.java index 90ef9572..27600659 100644 --- a/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDB.java +++ b/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDB.java @@ -7,34 +7,49 @@ package eu.itesla_project.iidm.ddb.eurostag; import java.io.IOException; +import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * @author Geoffroy Jamgotchian */ class EurostagDDB { + private static final Logger LOGGER = LoggerFactory.getLogger(EurostagDDB.class); + private final Map generators = new HashMap<>(); EurostagDDB(List ddbDirs) throws IOException { for (Path ddbDir : ddbDirs) { + ddbDir = readSymbolicLink(ddbDir); if (!Files.exists(ddbDir) && !Files.isDirectory(ddbDir)) { throw new IllegalArgumentException(ddbDir + " must exist and be a dir"); } - Files.walkFileTree(ddbDir, new SimpleFileVisitor() { + Files.walkFileTree(ddbDir, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (Files.isRegularFile(file) && file.toString().endsWith(".tg")) { - String fileName = file.getFileName().toString(); - generators.put(fileName.substring(0, fileName.length() - 3), file); + String fileName = file.getFileName().toString(); + Path tmpfile = readSymbolicLink(file); + if (Files.isDirectory(tmpfile)) { + Files.walkFileTree(tmpfile, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, this); + } else if (Files.isRegularFile(tmpfile) && fileName.endsWith(".tg")) { + String key = fileName.substring(0, fileName.length() - 3); + if (generators.containsKey(key)) { + LOGGER.warn("the processing has detected that the file {} is present in {} and {}", fileName, tmpfile, generators.get(key)); + } + generators.put(key, tmpfile); } return super.visitFile(file, attrs); } @@ -42,8 +57,16 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO } } - Path findGenerator(String idDdb) throws IOException { + Path findGenerator(String idDdb) { return generators.get(idDdb); } + private static Path readSymbolicLink(Path link) throws IOException { + Path path = link; + while (Files.isSymbolicLink(path)) { + path = Files.readSymbolicLink(path); + } + return path; + } + } diff --git a/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagStepUpTransformerInserter.java b/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagStepUpTransformerInserter.java index b70a29f2..6145b21c 100644 --- a/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagStepUpTransformerInserter.java +++ b/eurostag-step-up-transformer/src/main/java/eu/itesla_project/iidm/ddb/eurostag/EurostagStepUpTransformerInserter.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 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/. @@ -7,9 +8,6 @@ package eu.itesla_project.iidm.ddb.eurostag; import com.powsybl.computation.ComputationManager; -import eu.itesla_project.iidm.ddb.eurostag.model.PowerFlow; -import eu.itesla_project.iidm.ddb.eurostag.model.StateVariable; -import eu.itesla_project.iidm.ddb.eurostag.model.TransformerModel; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.ReactiveCapabilityCurve.Point; import com.powsybl.iidm.network.util.Identifiables; @@ -18,6 +16,9 @@ import com.powsybl.loadflow.LoadFlowFactory; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; +import eu.itesla_project.iidm.ddb.eurostag.model.PowerFlow; +import eu.itesla_project.iidm.ddb.eurostag.model.StateVariable; +import eu.itesla_project.iidm.ddb.eurostag.model.TransformerModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +40,7 @@ public class EurostagStepUpTransformerInserter { private final static float SB = 100; private final static float ACCEPTABLE_VOLTAGE_DIFF = 0.1f; - private final static float INFINITE_REACTIVE_LIMIT = 9999f; + private final static float INFINITE_REACTIVE_LIMIT = 99999f; public enum InsertionStatus { OK("ok"), @@ -301,7 +302,7 @@ private static void fillGeneratorState(Generator g, StateVariable sv) { } private static Generator moveGenerator(Generator srcGen, StateVariable srcSv, VoltageLevel destVl, Bus destBus, boolean connected, - Function fct, EurostagStepUpTransformerConfig config) { + Function fct, EurostagStepUpTransformerConfig config, TwoWindingsTransformer twt) { fillGeneratorState(srcGen, srcSv); @@ -367,6 +368,17 @@ private static Generator moveGenerator(Generator srcGen, StateVariable srcSv, Vo float newP = (float) -fct.apply(new StateVariable(-point.getP(), 0, srcSv.u, srcSv.theta)).p; float newMinQ = config.isNoReactiveLimits() ? -INFINITE_REACTIVE_LIMIT : (float) -fct.apply(new StateVariable(srcSv.p, -point.getMinQ(), srcSv.u, srcSv.theta)).q; float newMaxQ = config.isNoReactiveLimits() ? INFINITE_REACTIVE_LIMIT : (float) -fct.apply(new StateVariable(srcSv.p, -point.getMaxQ(), srcSv.u, srcSv.theta)).q; + + //test if the step-up transformer impedance is compatible with the reactive limit bounds: the maximun nominal power with a very high + //short-circuit power should be higher than the reactive bounds. If not, remove the bounds + float sMax = computeMaxRate(twt); + if ((sMax < Math.abs(newMinQ)) || (sMax < Math.abs(newMaxQ))) { + LOGGER.warn("Infinite limit mode activated for '{}': either abs({}) or abs({}) higher than {} (maximum nominal power with a short-circuit power of 40%)", + lvGen.getId(), newMinQ, newMaxQ, sMax); + newMinQ = -INFINITE_REACTIVE_LIMIT; + newMaxQ = INFINITE_REACTIVE_LIMIT; + } + LOGGER.trace("Resizing reactive limits of '{}': [{}, {}] -> [{}, {}]", lvGen.getId(), point.getMinQ(), point.getMaxQ(), newMinQ, newMaxQ); rcca.beginPoint() @@ -455,13 +467,27 @@ public static InsertionStatus insert(Generator hvGen, TG tg, IdDictionary auxDic Function fct = sv -> toLvGenPf(transformerModel, sv, hvAuxPf, lvAuxPf); StateVariable hvGenSv = new StateVariable(); - moveGenerator(hvGen, hvGenSv, lvVl, lvBus, hvGenBus != null, fct, config); + moveGenerator(hvGen, hvGenSv, lvVl, lvBus, hvGenBus != null, fct, config, twt); stateBefore.injections.put(twt.getId(), new PowerFlow((float) (hvGenSv.p + hvAuxPf.p), (float) (hvGenSv.q + hvAuxPf.q))); return InsertionStatus.OK; } + /** + * Compute a reasonable maximum nominal power ('rate') for a TwoWindingsTransformer + * with a very high short-circuit power of 40% + * + * @param twt two winding transformer + * @return maximum nominal power + */ + private static float computeMaxRate(TwoWindingsTransformer twt) { + Objects.requireNonNull(twt); + VoltageLevel u2 = twt.getTerminal2().getVoltageLevel(); + float z = SV.getX(twt); + return 0.4f * (float) Math.pow(u2.getNominalV(), 2) / z; + } + public static InsertionStatus insert(Generator g, Path ddbFile, IdDictionary auxDict, EurostagStepUpTransformerConfig config, StateBefore stateBefore) throws IOException { if (!Files.exists(ddbFile) && !Files.isRegularFile(ddbFile)) { throw new IllegalArgumentException(ddbFile + " must exist and be a file"); @@ -612,7 +638,7 @@ public void visitThreeWindingsTransformer(ThreeWindingsTransformer transformer, boolean connected = twt.getTerminal1().isConnected() && twt.getTerminal2().isConnected() && lvGen.getTerminal().isConnected(); StateVariable lvGenSv = new StateVariable(); - moveGenerator(lvGen, lvGenSv, hvVl, hvBus, connected, fct, config); + moveGenerator(lvGen, lvGenSv, hvVl, hvBus, connected, fct, config, twt); } for (Load aux : auxLs) { diff --git a/eurostag-step-up-transformer/src/test/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDBTest.java b/eurostag-step-up-transformer/src/test/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDBTest.java new file mode 100644 index 00000000..60bde347 --- /dev/null +++ b/eurostag-step-up-transformer/src/test/java/eu/itesla_project/iidm/ddb/eurostag/EurostagDDBTest.java @@ -0,0 +1,76 @@ +package eu.itesla_project.iidm.ddb.eurostag; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Test; + +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; + +public class EurostagDDBTest { + + @Test + public void testEurostagDDB() throws IOException { + try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { + Path folder1 = Files.createDirectory(fs.getPath("/folder1")); + Path folder2 = Files.createDirectory(fs.getPath("/folder2")); + Path folder3 = Files.createDirectory(fs.getPath("/folder3")); + + Path generator1 = Files.createFile(folder1.resolve("generator1.tg")); + Path generator2 = Files.createFile(folder1.resolve("generator2.tg")); + + Files.createFile(folder2.resolve("generator3.tg.bck")); + Path link = Files.createSymbolicLink(folder2.resolve("folder3"), folder3); + + Path generator4 = Files.createFile(link.resolve("generator4.tg")); + Path dataFile = Files.createFile(folder3.resolve("generator.data")); + Files.createSymbolicLink(folder3.resolve("generator5.tg"), dataFile); + + EurostagDDB eurostagDDB = new EurostagDDB(Arrays.asList(folder1, folder2)); + assertEquals(generator1, eurostagDDB.findGenerator("generator1")); + assertEquals(generator2, eurostagDDB.findGenerator("generator2")); + assertNull(eurostagDDB.findGenerator("generator3")); + assertEquals(generator4, eurostagDDB.findGenerator("generator4")); + assertEquals(dataFile, eurostagDDB.findGenerator("generator5")); + } + } + + @Test + public void testLinkFiles() throws IOException { + try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { + Path folder = Files.createDirectory(fs.getPath("/tmp")); + Path dataFile = Files.createFile(folder.resolve("generator.data")); + Files.createSymbolicLink(folder.resolve("generator1.tg"), dataFile); + Files.createSymbolicLink(folder.resolve("generator2.tg"), dataFile); + Files.createSymbolicLink(folder.resolve("generator3.tg"), dataFile); + Path generator4 = Files.createFile(folder.resolve("generator4.tg")); + + EurostagDDB eurostagDDB = new EurostagDDB(Collections.singletonList(folder)); + assertEquals(dataFile, eurostagDDB.findGenerator("generator1")); + assertEquals(dataFile, eurostagDDB.findGenerator("generator2")); + assertEquals(dataFile, eurostagDDB.findGenerator("generator3")); + assertEquals(generator4, eurostagDDB.findGenerator("generator4")); + } + } + + @Test + public void testLinkDirectory() throws IOException { + try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { + Path folder = Files.createDirectory(fs.getPath("/folder")); + Path file = Files.createFile(folder.resolve("generator.tg")); + Path linkFolder = Files.createSymbolicLink(fs.getPath("/work/folder.link"), folder); + + EurostagDDB eurostagDDB = new EurostagDDB(Collections.singletonList(linkFolder)); + assertEquals(file, eurostagDDB.findGenerator("generator")); + } + } + +} diff --git a/wca-integration/src/main/java/eu/itesla_project/wca/WCAHistoLimits.java b/wca-integration/src/main/java/eu/itesla_project/wca/WCAHistoLimits.java index 93934228..44cd2d4f 100644 --- a/wca-integration/src/main/java/eu/itesla_project/wca/WCAHistoLimits.java +++ b/wca-integration/src/main/java/eu/itesla_project/wca/WCAHistoLimits.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.*; @@ -79,16 +80,17 @@ public void load(Network network, HistoDbClient histoDbClient) throws IOExceptio public void write(DataSource dataSource, StringToIntMapper mapper) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(HISTO_LOADS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "loads historical data " + histoInterval, - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("num"), - new Column("min p (MW)"), - new Column("max p (MW)"), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(HISTO_LOADS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + "loads historical data " + histoInterval, + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("num"), + new Column("min p (MW)"), + new Column("max p (MW)"), + new Column("id"))) { for (Map.Entry> e : loadLimits.entrySet()) { String id = e.getKey(); @@ -110,16 +112,17 @@ public void write(DataSource dataSource, StringToIntMapper mapper) t } } - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(HISTO_GENERATORS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "generators historical data " + histoInterval, - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("num"), - new Column("min p (MW)"), - new Column("max p (MW)"), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(HISTO_GENERATORS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + "generators historical data " + histoInterval, + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("num"), + new Column("min p (MW)"), + new Column("max p (MW)"), + new Column("id"))) { for (Map.Entry> e : generatorLimits.entrySet()) { String id = e.getKey(); diff --git a/wca-integration/src/main/java/eu/itesla_project/wca/WCASecurityRulesWriter.java b/wca-integration/src/main/java/eu/itesla_project/wca/WCASecurityRulesWriter.java index 25c947f1..83de3535 100644 --- a/wca-integration/src/main/java/eu/itesla_project/wca/WCASecurityRulesWriter.java +++ b/wca-integration/src/main/java/eu/itesla_project/wca/WCASecurityRulesWriter.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Objects; @@ -136,23 +137,24 @@ private static WCAEntity toEntity(HistoDbNetworkAttributeId attrId, Network netw } public void write() { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(SECURITY_RULES_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "Security rules", - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("inequality num"), - new Column("convex num"), - new Column("var type (1: P, 2: Q, 3: V)"), - new Column("entity type (1: branch, 2: load, 3: generator, 4: compensator shunt, 5: substation)"), - new Column("entity num"), - new Column("branch side (1 or 2, 0 if NA)"), - new Column("inequality coeff."), - new Column("constant value"), - new Column("contingency num"), - new Column("security index type"), - new Column("attribute set (0: active only, 1: active/reactive)"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(SECURITY_RULES_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + "Security rules", + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("inequality num"), + new Column("convex num"), + new Column("var type (1: P, 2: Q, 3: V)"), + new Column("entity type (1: branch, 2: load, 3: generator, 4: compensator shunt, 5: substation)"), + new Column("entity num"), + new Column("branch side (1 or 2, 0 if NA)"), + new Column("inequality coeff."), + new Column("constant value"), + new Column("contingency num"), + new Column("security index type"), + new Column("attribute set (0: active only, 1: active/reactive)"))) { class Context { diff --git a/wca-integration/src/main/java/eu/itesla_project/wca/WCAUtils.java b/wca-integration/src/main/java/eu/itesla_project/wca/WCAUtils.java index 427a557c..83831b30 100644 --- a/wca-integration/src/main/java/eu/itesla_project/wca/WCAUtils.java +++ b/wca-integration/src/main/java/eu/itesla_project/wca/WCAUtils.java @@ -6,11 +6,7 @@ */ package eu.itesla_project.wca; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -176,14 +172,15 @@ public static void writeContingencies(Collection contingencies, Dat Objects.requireNonNull(contingencies); Objects.requireNonNull(dataSource); Objects.requireNonNull(mapper); - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(WCAConstants.FAULTS_FILE_SUFFIX, WCAConstants.TXT_EXT, false), StandardCharsets.UTF_8), - "Contingencies", - AmplConstants.INVALID_FLOAT_VALUE, - true, - AmplConstants.LOCALE, - new Column("num"), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(WCAConstants.FAULTS_FILE_SUFFIX, WCAConstants.TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + "Contingencies", + AmplConstants.INVALID_FLOAT_VALUE, + true, + AmplConstants.LOCALE, + new Column("num"), + new Column("id"))) { for (Contingency contingency : contingencies) { int contingencyNum = mapper.getInt(AmplSubset.FAULT, contingency.getId()); formatter.writeCell(contingencyNum) @@ -201,14 +198,15 @@ public static void writeActions(Collection actionIds, DataSource dataSou Objects.requireNonNull(mapper); Objects.requireNonNull(title); Objects.requireNonNull(amplSubset); - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(WCAConstants.ACTIONS_FILE_SUFFIX, WCAConstants.TXT_EXT, false), StandardCharsets.UTF_8), - title, - AmplConstants.INVALID_FLOAT_VALUE, - true, - AmplConstants.LOCALE, - new Column("num"), - new Column("id"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(WCAConstants.ACTIONS_FILE_SUFFIX, WCAConstants.TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + title, + AmplConstants.INVALID_FLOAT_VALUE, + true, + AmplConstants.LOCALE, + new Column("num"), + new Column("id"))) { for (String actionId : actionIds) { int actionNum = mapper.getInt(amplSubset, actionId); formatter.writeCell(actionNum) diff --git a/wca-integration/src/main/java/eu/itesla_project/wca/uncertainties/UncertaintiesAmplWriter.java b/wca-integration/src/main/java/eu/itesla_project/wca/uncertainties/UncertaintiesAmplWriter.java index 3d5c9044..cbf87a8d 100644 --- a/wca-integration/src/main/java/eu/itesla_project/wca/uncertainties/UncertaintiesAmplWriter.java +++ b/wca-integration/src/main/java/eu/itesla_project/wca/uncertainties/UncertaintiesAmplWriter.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.Objects; @@ -53,16 +54,17 @@ private int getNum(StochasticInjection inj, StringToIntMapper mapper } private void writeReductionMatrix(Uncertainties uncertainties, DataSource dataSource, StringToIntMapper mapper) throws IOException { - try (TableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(REDUCTION_MATRIX_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "Reduction matrix", - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("inj. type"), - new Column("inj. num"), - new Column("var. num"), - new Column("coeff."))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(REDUCTION_MATRIX_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + TableFormatter formatter = new AmplDatTableFormatter( + writer, + "Reduction matrix", + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("inj. type"), + new Column("inj. num"), + new Column("var. num"), + new Column("coeff."))) { for (int i = 0; i < uncertainties.reductionMatrix.length; i++) { StochasticInjection inj = uncertainties.injections.get(i); for (int varNum = 0; varNum < uncertainties.reductionMatrix[i].length; varNum++) { @@ -79,15 +81,16 @@ private void writeReductionMatrix(Uncertainties uncertainties, DataSource dataSo } private void writeTrustIntervals(Uncertainties uncertainties, DataSource dataSource) throws IOException { - try (AmplDatTableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(TRUST_INTERVAL_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "Trust intervals", - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("var. num"), - new Column("min"), - new Column("max"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(TRUST_INTERVAL_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + AmplDatTableFormatter formatter = new AmplDatTableFormatter( + writer, + "Trust intervals", + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("var. num"), + new Column("min"), + new Column("max"))) { for (int varNum = 0; varNum < uncertainties.min.length; varNum++) { formatter.writeCell(varNum + 1) .writeCell(uncertainties.min[varNum]) @@ -97,15 +100,16 @@ private void writeTrustIntervals(Uncertainties uncertainties, DataSource dataSou } private void writeMeans(Uncertainties uncertainties, DataSource dataSource, StringToIntMapper mapper) throws IOException { - try (AmplDatTableFormatter formatter = new AmplDatTableFormatter( - new OutputStreamWriter(dataSource.newOutputStream(MEANS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8), - "Means", - INVALID_FLOAT_VALUE, - true, - LOCALE, - new Column("inj. type"), - new Column("inj. num"), - new Column("mean"))) { + try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(MEANS_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); + AmplDatTableFormatter formatter = new AmplDatTableFormatter( + writer, + "Means", + INVALID_FLOAT_VALUE, + true, + LOCALE, + new Column("inj. type"), + new Column("inj. num"), + new Column("mean"))) { for (int i = 0; i < uncertainties.means.length; i++) { StochasticInjection inj = uncertainties.injections.get(i); formatter.writeCell(inj.getType().toChar())