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

Export buses voltage and update targets V #53

Merged
merged 31 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
390cbcd
Refactor output classes.
p-arvy Jan 12, 2024
45f790d
refactor.
p-arvy Jan 12, 2024
ac2840c
refactor.
p-arvy Jan 12, 2024
bdf9067
Add TU for wrong number of columns.
p-arvy Jan 12, 2024
69d77c7
Merge branch 'main' into refactor_outputs
annetill Jan 15, 2024
e494e7b
Small renaming.
annetill Jan 17, 2024
9ba7d6a
Add export of voltage plan.
p-arvy Jan 10, 2024
b289f5a
remove useless id.
p-arvy Jan 10, 2024
6b12105
Add TU for VoltagePlanOutput.
p-arvy Jan 10, 2024
5115f1b
update/add TU.
p-arvy Jan 10, 2024
2ef091c
refactor.
p-arvy Jan 10, 2024
711d14c
Add warm-start and TU.
p-arvy Jan 11, 2024
295119b
refactor.
p-arvy Jan 17, 2024
023995c
add boolean for warm start update and refactor TUs.
p-arvy Jan 17, 2024
0cd5922
fix codesmell.
p-arvy Jan 17, 2024
3f98bca
Merge branch 'main' into export_buses_voltage
annetill Jan 18, 2024
b107540
refactor.
p-arvy Jan 18, 2024
f9d1851
Merge remote-tracking branch 'origin/export_buses_voltage' into expor…
p-arvy Jan 18, 2024
c117747
refactor.
p-arvy Jan 18, 2024
adea8ae
fix codesmell.
p-arvy Jan 18, 2024
c43485a
Refactor and add TUs.
p-arvy Jan 25, 2024
bace3c3
refactor mock files.
p-arvy Jan 25, 2024
c4d8012
add TU for missing regulated bus.
p-arvy Jan 25, 2024
504f6f5
wip.
p-arvy Jan 25, 2024
03eb0a2
Add log when bus/regulation terminal is null.
p-arvy Jan 31, 2024
ae63972
improve coverage.
p-arvy Jan 31, 2024
0bc0314
keep same changes but on modifiable tap changers/shunts.
p-arvy Feb 1, 2024
e49f9aa
refactor.
p-arvy Feb 1, 2024
810b10f
fix codesmell.
p-arvy Feb 1, 2024
4d192d2
remove restriction on target V update.
p-arvy Feb 1, 2024
24704ce
Rework to clarify.
annetill Feb 5, 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 @@ -14,6 +14,7 @@
import com.powsybl.openreac.parameters.input.algo.AlgorithmInput;
import com.powsybl.openreac.parameters.output.OpenReacResult;
import com.powsybl.openreac.parameters.output.ReactiveSlackOutput;
import com.powsybl.openreac.parameters.output.VoltagePlanOutput;
import com.powsybl.openreac.parameters.output.network.NetworkModifications;

import java.util.ArrayList;
Expand All @@ -40,6 +41,7 @@ public class OpenReacAmplIOFiles implements AmplParameters {
private final VoltageLevelLimitsOverrideInput voltageLimitsOverride;
private final ConfiguredBusesWithReactiveSlack configuredReactiveSlackBuses;
private final NetworkModifications networkModifications;
private final VoltagePlanOutput voltagePlanOutput;
private final boolean debug;

public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean debug) {
Expand All @@ -54,6 +56,7 @@ public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean d
//outputs
this.reactiveSlackOutput = new ReactiveSlackOutput();
this.networkModifications = new NetworkModifications(network);
this.voltagePlanOutput = new VoltagePlanOutput();
p-arvy marked this conversation as resolved.
Show resolved Hide resolved

this.debug = debug;
}
Expand All @@ -66,6 +69,10 @@ public NetworkModifications getNetworkModifications() {
return networkModifications;
}

public VoltagePlanOutput getVoltagePlanOutput() {
return voltagePlanOutput;
}

@Override
public Collection<AmplInputFile> getInputParameters() {
return List.of(constantQGenerators, variableShuntCompensators, variableTwoWindingsTransformers,
Expand All @@ -76,9 +83,10 @@ public Collection<AmplInputFile> getInputParameters() {
public Collection<AmplOutputFile> getOutputParameters(boolean isConvergenceOk) {
if (isConvergenceOk) {
List<AmplOutputFile> networkModificationsOutputFiles = networkModifications.getOutputFiles();
List<AmplOutputFile> list = new ArrayList<>(networkModificationsOutputFiles.size() + 1);
List<AmplOutputFile> list = new ArrayList<>(networkModificationsOutputFiles.size() + 2);
list.addAll(networkModificationsOutputFiles);
list.add(reactiveSlackOutput);
list.add(voltagePlanOutput);
return list;
}
return List.of();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@

import com.powsybl.iidm.modification.*;
import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.*;
import com.powsybl.openreac.parameters.OpenReacAmplIOFiles;
import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack;
import org.jgrapht.alg.util.Pair;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;

/**
* OpenReac user interface to get results information.
Expand All @@ -32,6 +30,8 @@ public class OpenReacResult {
private final List<VscConverterStationModification> vscModifications;
private final List<StaticVarCompensatorModification> svcModifications;
private final List<RatioTapPositionModification> tapPositionModifications;
private final HashMap<String, Pair<Double, Double>> voltagePlan;
private boolean warmStart = true;

/**
* @param status the final status of the OpenReac run.
Expand All @@ -48,6 +48,7 @@ public OpenReacResult(OpenReacStatus status, OpenReacAmplIOFiles amplIOFiles, Ma
this.vscModifications = List.copyOf(amplIOFiles.getNetworkModifications().getVscModifications());
this.svcModifications = List.copyOf(amplIOFiles.getNetworkModifications().getSvcModifications());
this.tapPositionModifications = List.copyOf(amplIOFiles.getNetworkModifications().getTapPositionModifications());
this.voltagePlan = new HashMap<>(amplIOFiles.getVoltagePlanOutput().getVoltagePlan());
}

public OpenReacStatus getStatus() {
Expand Down Expand Up @@ -82,7 +83,19 @@ public List<VscConverterStationModification> getVscModifications() {
return vscModifications;
}

public List<NetworkModification> getAllModifs() {
public Map<String, Pair<Double, Double>> getVoltagePlan() {
return voltagePlan;
}

public boolean getWarmStat() {
p-arvy marked this conversation as resolved.
Show resolved Hide resolved
return warmStart;
}

public void setWarmStart(boolean warmStart) {
this.warmStart = warmStart;
}

public List<NetworkModification> getAllNetworkModifications() {
List<NetworkModification> modifs = new ArrayList<>(getGeneratorModifications().size() +
getShuntsModifications().size() +
getSvcModifications().size() +
Expand All @@ -97,8 +110,40 @@ public List<NetworkModification> getAllModifs() {
}

public void applyAllModifications(Network network) {
for (NetworkModification modif : getAllModifs()) {
for (NetworkModification modif : getAllNetworkModifications()) {
modif.apply(network);
}

// update target of ratio tap changers regulating voltage
network.getTwoWindingsTransformerStream()
p-arvy marked this conversation as resolved.
Show resolved Hide resolved
.filter(RatioTapChangerHolder::hasRatioTapChanger)
.map(RatioTapChangerHolder::getRatioTapChanger)
.filter(TapChanger::isRegulating)
.forEach(ratioTapChanger -> {
p-arvy marked this conversation as resolved.
Show resolved Hide resolved
Bus bus = ratioTapChanger.getRegulationTerminal().getBusView().getBus();
double v = voltagePlan.get(bus.getId()).getFirst();
ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV());
}
);

// update target of shunts regulating voltage
network.getShuntCompensatorStream()
.filter(ShuntCompensator::isVoltageRegulatorOn)
.forEach(shuntCompensator -> {
Bus bus = shuntCompensator.getRegulatingTerminal().getBusView().getBus();
double v = voltagePlan.get(bus.getId()).getFirst();
shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV());
});

// update voltages of the buses
if (getWarmStat()) {
for (var busUpdate : voltagePlan.entrySet()) {
Bus b = network.getBusView().getBus(busUpdate.getKey());
double v = busUpdate.getValue().getFirst();
p-arvy marked this conversation as resolved.
Show resolved Hide resolved
double angle = busUpdate.getValue().getSecond();
b.setV(v * b.getVoltageLevel().getNominalV());
b.setAngle(angle);
p-arvy marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2024, 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.parameters.output;

import com.powsybl.ampl.converter.AmplSubset;
import com.powsybl.commons.util.StringToIntMapper;
import com.powsybl.openreac.parameters.AmplIOUtils;
import org.jgrapht.alg.util.Pair;

import java.util.*;

/**
* @author Pierre Arvy <pierre.arvy at artelys.com>
*/
public class VoltagePlanOutput extends AbstractNoThrowOutput {

private static final String ELEMENT = "voltages";
public static final int EXPECTED_COLS = 5;
private static final int ID_COLUMN_INDEX = 4;
private static final int V_COLUMN_INDEX = 2;
private static final int ANGLE_COLUMN_INDEX = 3;

private final Map<String, Pair<Double, Double>> voltagePlan = new HashMap<>();

public Map<String, Pair<Double, Double>> getVoltagePlan() {
return voltagePlan;
}

@Override
public String getElement() {
return ELEMENT;
}

@Override
public int getExpectedColumns() {
return EXPECTED_COLS;
}

@Override
protected void readLine(String[] tokens, StringToIntMapper<AmplSubset> stringToIntMapper) {
String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]);
double v = readDouble(tokens[V_COLUMN_INDEX]);
double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]);
voltagePlan.put(id, Pair.of(v, angle));
}

@Override
public boolean throwOnMissingFile() {
triggerErrorState();
return false;
}

}
18 changes: 18 additions & 0 deletions open-reac/src/main/resources/openreac/reactiveopfoutput.run
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ close (fileOut);



###############################################################################
#
# Writing results for buses states
#
###############################################################################
if final_status == "OK" then {

let fileOut := "reactiveopf_results_voltages.csv";
printf "#variant;bus;V(pu);theta(rad);id;\n" > (fileOut);
printf {n in BUSCC} "%i;%i;%.3f;%.3f;%s;\n",
1, n, V[n], teta[n], '"' & bus_id[1,n] & '"'
> (fileOut);
close (fileOut);

}



###############################################################################
#
# Writing results for LCC converters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
Expand Down Expand Up @@ -200,7 +199,8 @@ public void testOutputFileParsing() throws IOException {
"mock_outputs/reactiveopf_results_rtc.csv",
"mock_outputs/reactiveopf_results_shunts.csv",
"mock_outputs/reactiveopf_results_static_var_compensators.csv",
"mock_outputs/reactiveopf_results_vsc_converter_stations.csv"));
"mock_outputs/reactiveopf_results_vsc_converter_stations.csv",
"mock_outputs/reactiveopf_results_voltages.csv"));
try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir),
localCommandExecutor, ForkJoinPool.commonPool())) {
OpenReacResult openReacResult = OpenReacRunner.run(network,
Expand All @@ -213,6 +213,7 @@ public void testOutputFileParsing() throws IOException {
assertEquals(1, openReacResult.getSvcModifications().size());
assertEquals(1, openReacResult.getVscModifications().size());
assertEquals(7, openReacResult.getGeneratorModifications().size());
assertEquals(3, openReacResult.getVoltagePlan().size());
assertEquals(82, openReacResult.getIndicators().size());
assertTrue(openReacResult.getReactiveSlacks().isEmpty());
}
Expand All @@ -230,7 +231,8 @@ void testRunAsync() throws IOException {
subFolder + "/reactiveopf_results_rtc.csv",
subFolder + "/reactiveopf_results_shunts.csv",
subFolder + "/reactiveopf_results_static_var_compensators.csv",
subFolder + "/reactiveopf_results_vsc_converter_stations.csv"));
subFolder + "/reactiveopf_results_vsc_converter_stations.csv",
subFolder + "/reactiveopf_results_voltages.csv"));
// To really run open reac, use the commented line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path
// try (ComputationManager computationManager = new LocalComputationManager()) {
try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir),
Expand All @@ -244,23 +246,7 @@ void testRunAsync() throws IOException {
}

private void testAllModifAndLoadFlow(Network network, String subFolder, OpenReacParameters parameters) throws IOException {
LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor(
List.of(subFolder + "/reactiveopf_results_generators.csv",
subFolder + "/reactiveopf_results_indic.txt",
subFolder + "/reactiveopf_results_rtc.csv",
subFolder + "/reactiveopf_results_shunts.csv",
subFolder + "/reactiveopf_results_static_var_compensators.csv",
subFolder + "/reactiveopf_results_vsc_converter_stations.csv"));
// To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path
// try (ComputationManager computationManager = new LocalComputationManager()) {
try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir),
localCommandExecutor, ForkJoinPool.commonPool())) {
OpenReacResult openReacResult = OpenReacRunner.run(network,
network.getVariantManager().getWorkingVariantId(), parameters, new OpenReacConfig(true),
computationManager);
assertEquals(OpenReacStatus.OK, openReacResult.getStatus());
openReacResult.applyAllModifications(network);
}
runAndApplyAllModifications(network, subFolder, parameters, true);
LoadFlowResult loadFlowResult = LoadFlow.run(network);
assertTrue(loadFlowResult.isOk());
}
Expand Down Expand Up @@ -295,23 +281,37 @@ public void testSvc() throws IOException {
}

@Test
public void testShuntReconnection() throws IOException {
void testShunt() throws IOException {
Network network = create();
setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network
ShuntCompensator shunt = network.getShuntCompensator("SHUNT");
assertFalse(shunt.getTerminal().isConnected());
assertEquals(393, shunt.getTargetV());

OpenReacParameters parameters = new OpenReacParameters();
parameters.addVariableShuntCompensators(List.of("SHUNT"));
parameters.addVariableShuntCompensators(List.of(shunt.getId()));
testAllModifAndLoadFlow(network, "openreac-output-shunt", parameters);
assertTrue(shunt.getTerminal().isConnected()); // shunt has been reconnected
assertEquals(420.8, shunt.getTargetV()); // targetV has been updated
}

@Test
public void testTransformer() throws IOException {
Network network = VoltageControlNetworkFactory.createNetworkWithT2wt();
setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network
network.getTwoWindingsTransformer("T2wT").getRatioTapChanger().setTapPosition(2);
RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger()
.setTapPosition(2)
.setTargetDeadband(0)
.setRegulating(true);
assertEquals(2, rtc.getTapPosition());
assertEquals(33.0, rtc.getTargetV());

OpenReacParameters parameters = new OpenReacParameters();
parameters.addConstantQGenerators(List.of("GEN_1"));
parameters.addVariableTwoWindingsTransformers(List.of("T2wT"));
testAllModifAndLoadFlow(network, "openreac-output-transfo", parameters);
assertEquals(0, rtc.getTapPosition());
assertEquals(22.935, rtc.getTargetV());
}

@Test
Expand All @@ -322,6 +322,52 @@ public void testRealNetwork() throws IOException {
testAllModifAndLoadFlow(network, "openreac-output-real-network", parameters);
}

@Test
void testWarmStart() throws IOException {
Network network = VoltageControlNetworkFactory.createNetworkWithT2wt();
setDefaultVoltageLimits(network);
String subFolder = "openreac-output-warm-start";
OpenReacParameters parameters = new OpenReacParameters();

runAndApplyAllModifications(network, subFolder, parameters, false); // without warm start, no update
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_1").getV());
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_1").getAngle());
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_2").getV());
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_2").getAngle());
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_3").getV());
assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_3").getAngle());

runAndApplyAllModifications(network, subFolder, parameters, true);
assertEquals(119.592, network.getBusBreakerView().getBus("BUS_1").getV());
assertEquals(0.014, network.getBusBreakerView().getBus("BUS_1").getAngle());
assertEquals(118.8, network.getBusBreakerView().getBus("BUS_2").getV());
assertEquals(0, network.getBusBreakerView().getBus("BUS_2").getAngle());
assertEquals(22.935, network.getBusBreakerView().getBus("BUS_3").getV());
assertEquals(-0.082, network.getBusBreakerView().getBus("BUS_3").getAngle());
}

private void runAndApplyAllModifications(Network network, String subFolder, OpenReacParameters parameters, boolean warmStart) throws IOException {
LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor(
List.of(subFolder + "/reactiveopf_results_generators.csv",
subFolder + "/reactiveopf_results_indic.txt",
subFolder + "/reactiveopf_results_rtc.csv",
subFolder + "/reactiveopf_results_shunts.csv",
subFolder + "/reactiveopf_results_static_var_compensators.csv",
subFolder + "/reactiveopf_results_vsc_converter_stations.csv",
subFolder + "/reactiveopf_results_voltages.csv"));
// To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path
// try (ComputationManager computationManager = new LocalComputationManager()) {
try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir),
localCommandExecutor, ForkJoinPool.commonPool())) {
OpenReacResult openReacResult = OpenReacRunner.run(network,
network.getVariantManager().getWorkingVariantId(), parameters,
new OpenReacConfig(true), computationManager);
assertEquals(OpenReacStatus.OK, openReacResult.getStatus());
openReacResult.setWarmStart(warmStart);
openReacResult.applyAllModifications(network);
}
}

public static Network create() {
Network network = Network.create("svc", "test");
Substation s1 = network.newSubstation()
Expand Down
Loading
Loading