diff --git a/open-reac/pom.xml b/open-reac/pom.xml index 753d7ee4..44bcf018 100644 --- a/open-reac/pom.xml +++ b/open-reac/pom.xml @@ -101,15 +101,6 @@ com.powsybl powsybl-loadflow-api - - com.powsybl - powsybl-tools - - - - com.google.auto.service - auto-service - org.junit.jupiter diff --git a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java deleted file mode 100644 index 6c4bb036..00000000 --- a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java +++ /dev/null @@ -1,243 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package com.powsybl.openreac; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.google.auto.service.AutoService; -import com.powsybl.commons.PowsyblException; -import com.powsybl.computation.local.LocalComputationManager; -import com.powsybl.iidm.network.ImportConfig; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.tools.ConversionToolUtils; -import com.powsybl.loadflow.LoadFlow; -import com.powsybl.loadflow.LoadFlowParameters; -import com.powsybl.loadflow.LoadFlowResult; -import com.powsybl.openreac.exceptions.InvalidParametersException; -import com.powsybl.openreac.parameters.input.OpenReacParameters; -import com.powsybl.openreac.parameters.input.VoltageLimitOverride; -import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; -import com.powsybl.openreac.parameters.output.OpenReacResult; -import com.powsybl.tools.Command; -import com.powsybl.tools.Tool; -import com.powsybl.tools.ToolRunningContext; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.*; - -import static com.powsybl.iidm.network.tools.ConversionToolUtils.*; - -/** - * @author Nicolas Pierre - */ -@AutoService(Tool.class) -public class OpenReacTool implements Tool { - private static final String CASE_FILE = "case-file"; - private static final String SHUNTS_LIST = "variable-shunts-list"; - private static final String GENERATORS_LIST = "fixed-generators-list"; - private static final String TRANSFORMER_LIST = "variable-transformers-list"; - private static final String VOLTAGE_OVERRIDE_LIST = "voltage-level-override"; - private static final String OPEN_REAC_PARAMS = "open-reac-params"; - public static final String EXECUTION_OPENREAC = "execution/openreac"; - - @Override - public Command getCommand() { - return new Command() { - @Override - public String getName() { - return "open-reac"; - } - - @Override - public String getTheme() { - return "Optimal Power Flow"; - } - - @Override - public String getDescription() { - return "An optimal powerflow on reactive components"; - } - - public Options getOptions() { - Options options = new Options(); - options.addOption(Option.builder() - .longOpt(CASE_FILE) - .desc("the case path") - .hasArg() - .argName("FILE") - .required() - .build()); - options.addOption(createImportParametersFileOption()); - options.addOption(createImportParameterOption()); - options.addOption(createExportParametersFileOption()); - options.addOption(createExportParameterOption()); - options.addOption(Option.builder() - .longOpt(OPEN_REAC_PARAMS) - .desc("the OpenReac configuation file") - .hasArg() - .argName("OPEN_REAC_PARAM_FILE") - .build()); - return options; - } - - @Override - public String getUsageFooter() { - return null; - } - }; - } - - @Override - public void run(CommandLine commandLine, ToolRunningContext context) throws Exception { - // getting parameters - Path inputCaseFile = context.getFileSystem().getPath(commandLine.getOptionValue(CASE_FILE)); - Files.createDirectories(context.getFileSystem().getPath(EXECUTION_OPENREAC)); - context.getOutputStream().println("Parsing properties..."); - Properties inputParams = readProperties(commandLine, ConversionToolUtils.OptionType.IMPORT, context); - OpenReacParameters openReacParameters = createOpenReacParameters(commandLine, context); - - context.getOutputStream().println("Loading network '" + inputCaseFile + "'..."); - Network network = loadingNetwork(context, inputCaseFile, inputParams); - - itoolsOpenReac(context, network, openReacParameters); - - context.getOutputStream().println("Running a loadflow..."); - LoadFlowResult result = LoadFlow.run(network, context.getShortTimeExecutionComputationManager(), LoadFlowParameters.load()); - exportLoadFlowMetrics(context, result.getMetrics()); - context.getOutputStream().println("Loadflow done. Is ok ? " + result.isOk()); - - itoolsOpenReac(context, network, openReacParameters); - - context.getOutputStream().println("All good. Exiting..."); - } - - public void exportLoadFlowMetrics(ToolRunningContext context, Map metrics) throws IOException { - StringBuilder builder = new StringBuilder(); - for (Map.Entry metric : metrics.entrySet()) { - builder.append(metric.getKey()).append(" ").append(metric.getValue()).append(System.lineSeparator()); - } - Files.writeString(context.getFileSystem().getPath("./loadflow_metrics.txt"), builder.toString(), StandardOpenOption.CREATE); - } - - public OpenReacParameters createOpenReacParameters(CommandLine line, - ToolRunningContext context) throws IOException { - - String filename = line.getOptionValue(OPEN_REAC_PARAMS, null); - JsonNode jsonNode = new ObjectMapper().readTree("{}"); - if (filename != null) { - try (InputStream inputStream = Files.newInputStream(context.getFileSystem().getPath(filename))) { - if (filename.endsWith(".json")) { - jsonNode = new ObjectMapper().readTree(inputStream); - } else { - throw new InvalidParametersException("Format of properties must be json."); - } - } - } - - OpenReacParameters openReacParameters = new OpenReacParameters(); - if (jsonNode.get(SHUNTS_LIST) != null && jsonNode.get(SHUNTS_LIST).isArray()) { - ArrayNode array = (ArrayNode) jsonNode.get(SHUNTS_LIST); - array.forEach(node -> openReacParameters.addVariableShuntCompensators(List.of(node.asText()))); - } - if (jsonNode.get(GENERATORS_LIST) != null && jsonNode.get(GENERATORS_LIST).isArray()) { - ArrayNode array = (ArrayNode) jsonNode.get(GENERATORS_LIST); - array.forEach(node -> openReacParameters.addConstantQGenerators(List.of(node.asText()))); - } - if (jsonNode.get(TRANSFORMER_LIST) != null && jsonNode.get(TRANSFORMER_LIST).isArray()) { - ArrayNode array = (ArrayNode) jsonNode.get(TRANSFORMER_LIST); - array.forEach(node -> openReacParameters.addVariableTwoWindingsTransformers(List.of(node.asText()))); - } - if (jsonNode.get(VOLTAGE_OVERRIDE_LIST) != null && jsonNode.get(VOLTAGE_OVERRIDE_LIST).isArray()) { - ArrayNode array = (ArrayNode) jsonNode.get(VOLTAGE_OVERRIDE_LIST); - array.forEach(node -> { - String voltageId = node.get("id").asText(); - double lower = node.get("lower").asDouble(); - double upper = node.get("upper").asDouble(); - - List voltageLimitOverrides = new ArrayList<>(); - voltageLimitOverrides.add(new VoltageLimitOverride(voltageId, VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, lower)); - voltageLimitOverrides.add(new VoltageLimitOverride(voltageId, VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, upper)); - openReacParameters.addSpecificVoltageLimits(voltageLimitOverrides); - }); - } - boolean objectiveSet = false; - for (Iterator it = jsonNode.fieldNames(); it.hasNext(); ) { - String key = it.next(); - if (!key.equals(SHUNTS_LIST) && !key.equals(GENERATORS_LIST) && !key.equals(TRANSFORMER_LIST)) { - switch (key) { - case "obj_min_gen": - if (objectiveSet) { - throw new InvalidParametersException("Objective is set twice in JSON. Please put only one."); - } - openReacParameters.setObjective(OpenReacOptimisationObjective.MIN_GENERATION); - objectiveSet = true; - break; - case "obj_provided_target_v": - if (objectiveSet) { - throw new InvalidParametersException("Objective is set twice in JSON. Please put only one."); - } - openReacParameters.setObjective(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE); - objectiveSet = true; - break; - case "obj_target_ratio": - if (objectiveSet) { - throw new InvalidParametersException("Objective is set twice in JSON. Please put only one."); - - } - if (jsonNode.get(key).isNull()) { - throw new InvalidParametersException("obj_target_ratio must have a value indicating the ratio to nominal voltage level to target."); - } - double ratio = jsonNode.get(key).asDouble(); - openReacParameters.setObjectiveDistance(ratio); - openReacParameters.setObjective(OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT); - objectiveSet = true; - break; - default: - openReacParameters.addAlgorithmParam(key, jsonNode.get(key).asText()); - } - } - } - return openReacParameters; - } - - public void itoolsOpenReac(ToolRunningContext context, Network network, - OpenReacParameters openReacParameters) throws IOException { - context.getOutputStream().println("Running OpenReac on the network..."); - OpenReacConfig config = new OpenReacConfig(true); - OpenReacResult results; - try (LocalComputationManager computationManager = new LocalComputationManager(context.getFileSystem().getPath(EXECUTION_OPENREAC))) { - results = OpenReacRunner.run(network, network.getVariantManager().getWorkingVariantId(), openReacParameters, config, computationManager); - // Finding the last folder modified in the directory of the LocalComputationManager to tell the user which folder correspond. - String[] amplRunningFolderList = context.getFileSystem().getPath(EXECUTION_OPENREAC).toFile().list(); - Objects.requireNonNull(amplRunningFolderList, "OpenReac did not run in the specified folder. Unexpected error."); - Optional workingDir = Arrays.stream(amplRunningFolderList) - .map(filename -> context.getFileSystem().getPath(EXECUTION_OPENREAC, filename)) - .max(Comparator.comparing(path -> path.toFile().lastModified())); - context.getOutputStream().println("OpenReac optimisation done in " + workingDir.map(p -> p.toAbsolutePath().toString()).orElse("NOT_FOUND")); - } - - context.getOutputStream().println("OpenReac status : " + results.getStatus().name()); - - } - - public Network loadingNetwork(ToolRunningContext context, Path inputCaseFile, Properties inputParams) { - Network network = Network.read(inputCaseFile, context.getShortTimeExecutionComputationManager(), - ImportConfig.load(), inputParams); - if (network == null) { - throw new PowsyblException("Case '" + inputCaseFile + "' not found."); - } - return network; - } -} diff --git a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java deleted file mode 100644 index 230917d2..00000000 --- a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package com.powsybl.openreac; - -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; -import com.powsybl.computation.local.LocalComputationManager; -import com.powsybl.openreac.parameters.input.OpenReacParameters; -import com.powsybl.openreac.parameters.input.VoltageLimitOverride; -import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; -import com.powsybl.tools.ToolRunningContext; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.ParseException; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Nicolas PIERRE - */ -class ItoolsTest { - private FileSystem fileSystem; - private OpenReacTool tool; - private ToolRunningContext context; - - @BeforeEach - public void setUp() throws IOException { - tool = new OpenReacTool(); - fileSystem = Jimfs.newFileSystem(Configuration.unix()); - context = new ToolRunningContext(System.out, System.err, fileSystem, - new LocalComputationManager(), new LocalComputationManager()); - } - - @Test - public void testCommandLineBasic() { - String minimalLine = "--case-file network.iidm"; - assertDoesNotThrow(() -> new DefaultParser().parse(tool.getCommand().getOptions(), minimalLine.split(" ")), "minimal arguments should be input network"); - - String specificOpenReacLine = "--case-file network.xiidm --open-reac-params params.txt"; - assertDoesNotThrow(() -> new DefaultParser().parse(tool.getCommand().getOptions(), minimalLine.split(" ")), "OpenReac Tool should handle all those args " + specificOpenReacLine); - - } - - @Test - public void testCreateOpenReacParameters() throws ParseException, IOException { - Files.copy(getClass().getResourceAsStream("/openreac-params.json"), fileSystem.getPath("params.json")); - String line = "--case-file network.iidm --open-reac-params params.json"; - CommandLine cmdLine = new DefaultParser().parse(tool.getCommand().getOptions(), line.split(" ")); - OpenReacParameters loadedParams = tool.createOpenReacParameters(cmdLine, context); - assertEquals(List.of("2-winding-transfo"), loadedParams.getVariableTwoWindingsTransformers(), "Parsing of OpenReac parameters is wrong."); - assertEquals(List.of("constant-q-gen"), loadedParams.getConstantQGenerators(), "Parsing of OpenReac parameters is wrong."); - assertEquals(List.of("var-shunt", "var-shunt-2"), loadedParams.getVariableShuntCompensators(), "Parsing of OpenReac parameters is wrong."); - - // List of voltage limit overrides - List vloList = new ArrayList<>(); - vloList.add(new VoltageLimitOverride("voltageLevelId", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -5)); - vloList.add(new VoltageLimitOverride("voltageLevelId", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 5)); - - for (int i = 0; i < vloList.size(); i++) { - assertEquals(vloList.get(i), loadedParams.getSpecificVoltageLimits().get(i)); - } - assertEquals(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE, loadedParams.getObjective(), "Parsing of OpenReac parameters is wrong."); - } - -} diff --git a/open-reac/src/test/resources/openreac-params.json b/open-reac/src/test/resources/openreac-params.json deleted file mode 100644 index 7a771d75..00000000 --- a/open-reac/src/test/resources/openreac-params.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "obj_provided_target_v" : null, - "variable-shunts-list" : ["var-shunt", "var-shunt-2"], - "fixed-generators-list" : ["constant-q-gen"], - "variable-transformers-list" : ["2-winding-transfo"], - "voltage-level-override" : [ - { - "id": "voltageLevelId", - "lower": "-5", - "upper": "5" - } - ] -}