Skip to content

Commit

Permalink
add regulating element for generator, vsc and svc creation (#683)
Browse files Browse the repository at this point in the history
add regulating element for generator, vsc and svc creation
---------

Signed-off-by: Etienne LESOT <[email protected]>
  • Loading branch information
EtienneLt authored Jan 11, 2024
1 parent 5af67a3 commit a9c7efd
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 77 deletions.
4 changes: 2 additions & 2 deletions docs/user_guide/flowdecomposition.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ As we cannot set a PST on an interconnection, we set an equivalent null load cal
>>> network.get_generators()
name energy_source target_p min_p max_p min_q max_q rated_s reactive_limits_kind target_v target_q voltage_regulator_on regulated_element_id p q i voltage_level_id bus_id connected
id
FGEN 11_generator OTHER 100.0 -1000.0 1000.0 -1000.0 1000.0 NaN MIN_MAX 400.0 0.0 True NaN NaN NaN FGEN 1 FGEN 1_0 True
BLOAD 12_generator OTHER 100.0 -1000.0 1000.0 -1000.0 1000.0 NaN MIN_MAX 400.0 0.0 True NaN NaN NaN BLOAD 1 BLOAD 1_1 True
FGEN 11_generator OTHER 100.0 -1000.0 1000.0 -1000.0 1000.0 NaN MIN_MAX 400.0 0.0 True FGEN 11_generator NaN NaN NaN FGEN 1 FGEN 1_0 True
BLOAD 12_generator OTHER 100.0 -1000.0 1000.0 -1000.0 1000.0 NaN MIN_MAX 400.0 0.0 True BLOAD 12_generator NaN NaN NaN BLOAD 1 BLOAD 1_1 True
>>> network.get_loads()
name type p0 q0 p q i voltage_level_id bus_id connected
id
Expand Down
4 changes: 2 additions & 2 deletions docs/user_guide/network.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ For example, you can retrieve generators data as follows:
>>> network.get_generators() # doctest: +NORMALIZE_WHITESPACE
name energy_source target_p min_p max_p min_q max_q rated_s reactive_limits_kind target_v target_q voltage_regulator_on regulated_element_id p q i voltage_level_id bus_id connected
id
GEN OTHER 607.0 -9999.99 4999.0 -9.999990e+03 9.999990e+03 NaN MIN_MAX 24.5 301.0 True NaN NaN NaN VLGEN VLGEN_0 True
GEN2 OTHER 607.0 -9999.99 4999.0 -1.797693e+308 1.797693e+308 NaN MIN_MAX 24.5 301.0 True NaN NaN NaN VLGEN VLGEN_0 True
GEN OTHER 607.0 -9999.99 4999.0 -9.999990e+03 9.999990e+03 NaN MIN_MAX 24.5 301.0 True GEN NaN NaN NaN VLGEN VLGEN_0 True
GEN2 OTHER 607.0 -9999.99 4999.0 -1.797693e+308 1.797693e+308 NaN MIN_MAX 24.5 301.0 True GEN2 NaN NaN NaN VLGEN VLGEN_0 True

Most dataframes are indexed on the ID of the elements.
However, some more complex dataframes have a multi-index : for example,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ static NetworkDataframeMapper generators() {
.doubles("target_v", Generator::getTargetV, Generator::setTargetV)
.doubles("target_q", Generator::getTargetQ, Generator::setTargetQ)
.booleans("voltage_regulator_on", Generator::isVoltageRegulatorOn, Generator::setVoltageRegulatorOn)
.strings("regulated_element_id", NetworkDataframes::getRegulatedElementId, NetworkDataframes::setRegulatedElement)
.strings("regulated_element_id", generator -> NetworkUtil.getRegulatedElementId(generator::getRegulatingTerminal),
(generator, elementId) -> NetworkUtil.setRegulatingTerminal(generator::setRegulatingTerminal, generator.getNetwork(), elementId))
.doubles("p", getP(), setP())
.doubles("q", getQ(), setQ())
.doubles("i", g -> g.getTerminal().getI())
Expand All @@ -275,48 +276,6 @@ static NetworkDataframeMapper generators() {
.build();
}

private static String getRegulatedElementId(Injection<?> injection) {
Terminal terminal;
if (injection instanceof Generator generator) {
terminal = generator.getRegulatingTerminal();
} else if (injection instanceof VscConverterStation converterStation) {
terminal = converterStation.getRegulatingTerminal();
} else if (injection instanceof StaticVarCompensator svc) {
terminal = svc.getRegulatingTerminal();
} else {
throw new UnsupportedOperationException(String.format("%s is neither a generator, a vsc station or a var static compensator", injection.getId()));
}
if (terminal.getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) {
//Not supported for the moment
return null;
}
return terminal.getConnectable() != null ? terminal.getConnectable().getId() : null;
}

private static void setRegulatedElement(Injection<?> injection, String elementId) {
Network network = injection.getNetwork();
Identifiable<?> identifiable = network.getIdentifiable(elementId);
if (identifiable instanceof Injection) {
Terminal terminal = ((Injection<?>) identifiable).getTerminal();
if (terminal.getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) {
throw new UnsupportedOperationException("Cannot set regulated element to " + elementId +
": not currently supported for bus breaker topologies.");
}
if (injection instanceof Generator) {
((Generator) injection).setRegulatingTerminal(((Injection<?>) identifiable).getTerminal());
} else if (injection instanceof VscConverterStation) {
((VscConverterStation) injection).setRegulatingTerminal(((Injection<?>) identifiable).getTerminal());
} else if (injection instanceof StaticVarCompensator) {
((StaticVarCompensator) injection).setRegulatingTerminal(((Injection<?>) identifiable).getTerminal());
} else {
throw new UnsupportedOperationException(String.format("%s is neither a generator, a vsc station or a var static compensator", injection.getId()));
}
} else {
throw new UnsupportedOperationException("Cannot set regulated element to " + elementId +
": the regulated element may only be a busbar section or an injection.");
}
}

private static NetworkDataframeMapper subNetworks() {
return NetworkDataframeMapperBuilder.ofStream(n -> n.getSubnetworks().stream(),
getOrThrow(Network::getSubnetwork, "SubNetwork"))
Expand Down Expand Up @@ -656,7 +615,8 @@ static NetworkDataframeMapper vscs() {
.doubles("target_v", VscConverterStation::getVoltageSetpoint, VscConverterStation::setVoltageSetpoint)
.doubles("target_q", VscConverterStation::getReactivePowerSetpoint, VscConverterStation::setReactivePowerSetpoint)
.booleans("voltage_regulator_on", VscConverterStation::isVoltageRegulatorOn, VscConverterStation::setVoltageRegulatorOn)
.strings("regulated_element_id", NetworkDataframes::getRegulatedElementId, NetworkDataframes::setRegulatedElement)
.strings("regulated_element_id", vsc -> NetworkUtil.getRegulatedElementId(vsc::getRegulatingTerminal),
(vsc, elementId) -> NetworkUtil.setRegulatingTerminal(vsc::setRegulatingTerminal, vsc.getNetwork(), elementId))
.doubles("p", getP(), setP())
.doubles("q", getQ(), setQ())
.doubles("i", st -> st.getTerminal().getI())
Expand All @@ -680,7 +640,8 @@ private static NetworkDataframeMapper svcs() {
.doubles("target_q", StaticVarCompensator::getReactivePowerSetpoint, StaticVarCompensator::setReactivePowerSetpoint)
.enums("regulation_mode", StaticVarCompensator.RegulationMode.class,
StaticVarCompensator::getRegulationMode, StaticVarCompensator::setRegulationMode)
.strings("regulated_element_id", NetworkDataframes::getRegulatedElementId, NetworkDataframes::setRegulatedElement)
.strings("regulated_element_id", svc -> NetworkUtil.getRegulatedElementId(svc::getRegulatingTerminal),
(svc, elementId) -> NetworkUtil.setRegulatingTerminal(svc::setRegulatingTerminal, svc.getNetwork(), elementId))
.doubles("p", getP(), setP())
.doubles("q", getQ(), setQ())
.doubles("i", st -> st.getTerminal().getI())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
import com.powsybl.dataframe.update.IntSeries;
import com.powsybl.dataframe.update.StringSeries;
import com.powsybl.dataframe.update.UpdatingDataframe;
import com.powsybl.iidm.network.EnergySource;
import com.powsybl.iidm.network.GeneratorAdder;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.*;
import com.powsybl.python.network.NetworkUtil;

import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -43,7 +42,8 @@ public class GeneratorDataframeAdder extends AbstractSimpleAdder {
SeriesMetadata.doubles("target_q"),
SeriesMetadata.doubles("rated_s"),
SeriesMetadata.doubles("target_v"),
SeriesMetadata.booleans("voltage_regulator_on")
SeriesMetadata.booleans("voltage_regulator_on"),
SeriesMetadata.strings("regulating_element_id")
);

@Override
Expand All @@ -63,6 +63,7 @@ private static class GeneratorSeries extends InjectionSeries {
private final IntSeries voltageRegulatorOn;
private final StringSeries energySource;
private final StringSeries busOrBusbarSections;
private final StringSeries regulatingElements;

GeneratorSeries(UpdatingDataframe dataframe) {
super(dataframe);
Expand All @@ -76,11 +77,13 @@ private static class GeneratorSeries extends InjectionSeries {
this.voltageRegulatorOn = dataframe.getInts("voltage_regulator_on");
this.energySource = dataframe.getStrings("energy_source");
this.busOrBusbarSections = dataframe.getStrings("bus_or_busbar_section_id");
this.regulatingElements = dataframe.getStrings("regulating_element_id");
}

GeneratorAdder createAdder(Network network, int row) {
GeneratorAdder adder = getVoltageLevelOrThrowWithBusOrBusbarSectionId(network, row, voltageLevels, busOrBusbarSections)
.newGenerator();

setInjectionAttributes(adder, row);
applyIfPresent(maxP, row, adder::setMaxP);
applyIfPresent(minP, row, adder::setMinP);
Expand All @@ -90,6 +93,8 @@ GeneratorAdder createAdder(Network network, int row) {
applyIfPresent(ratedS, row, adder::setRatedS);
applyBooleanIfPresent(voltageRegulatorOn, row, adder::setVoltageRegulatorOn);
applyIfPresent(energySource, row, EnergySource.class, adder::setEnergySource);
applyIfPresent(regulatingElements, row, elementId -> NetworkUtil
.setRegulatingTerminal(adder::setRegulatingTerminal, network, elementId));
return adder;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
import com.powsybl.dataframe.update.DoubleSeries;
import com.powsybl.dataframe.update.StringSeries;
import com.powsybl.dataframe.update.UpdatingDataframe;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.StaticVarCompensator;
import com.powsybl.iidm.network.StaticVarCompensatorAdder;
import com.powsybl.iidm.network.*;
import com.powsybl.python.network.NetworkUtil;

import java.util.Collections;
import java.util.List;
Expand All @@ -39,7 +38,8 @@ public class SvcDataframeAdder extends AbstractSimpleAdder {
SeriesMetadata.doubles("b_min"),
SeriesMetadata.strings("regulation_mode"),
SeriesMetadata.doubles("target_v"),
SeriesMetadata.doubles("target_q")
SeriesMetadata.doubles("target_q"),
SeriesMetadata.strings("regulating_element_id")
);

@Override
Expand All @@ -56,6 +56,7 @@ private static class StaticVarCompensatorSeries extends InjectionSeries {
private final DoubleSeries targetV;
private final DoubleSeries targetQ;
private final StringSeries busOrBusbarSections;
private final StringSeries regulatingElements;

StaticVarCompensatorSeries(UpdatingDataframe dataframe) {
super(dataframe);
Expand All @@ -66,6 +67,7 @@ private static class StaticVarCompensatorSeries extends InjectionSeries {
this.targetV = dataframe.getDoubles("target_v");
this.regulationModes = dataframe.getStrings("regulation_mode");
this.busOrBusbarSections = dataframe.getStrings("bus_or_busbar_section_id");
this.regulatingElements = dataframe.getStrings("regulating_element_id");
}

StaticVarCompensatorAdder createAdder(Network network, int row) {
Expand All @@ -77,6 +79,8 @@ StaticVarCompensatorAdder createAdder(Network network, int row) {
applyIfPresent(targetQ, row, adder::setReactivePowerSetpoint);
applyIfPresent(targetV, row, adder::setVoltageSetpoint);
applyIfPresent(regulationModes, row, StaticVarCompensator.RegulationMode.class, adder::setRegulationMode);
applyIfPresent(regulatingElements, row, elementId -> NetworkUtil
.setRegulatingTerminal(adder::setRegulatingTerminal, network, elementId));
return adder;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.dataframe.network.adders;

import com.powsybl.commons.PowsyblException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.dataframe.update.UpdatingDataframe;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VscConverterStationAdder;
import com.powsybl.python.network.NetworkUtil;

import java.util.Collections;
import java.util.List;
Expand All @@ -39,7 +40,8 @@ public class VscStationDataframeAdder extends AbstractSimpleAdder {
SeriesMetadata.doubles("target_v"),
SeriesMetadata.doubles("target_q"),
SeriesMetadata.doubles("loss_factor"),
SeriesMetadata.booleans("voltage_regulator_on")
SeriesMetadata.booleans("voltage_regulator_on"),
SeriesMetadata.strings("regulating_element_id")
);

@Override
Expand All @@ -55,6 +57,7 @@ private static class VscStationSeries extends InjectionSeries {
private final DoubleSeries targetQ;
private final IntSeries voltageRegulatorOn;
private final StringSeries busOrBusbarSections;
private final StringSeries regulatingElements;

VscStationSeries(UpdatingDataframe dataframe) {
super(dataframe);
Expand All @@ -64,6 +67,7 @@ private static class VscStationSeries extends InjectionSeries {
this.targetQ = dataframe.getDoubles("target_q");
this.voltageRegulatorOn = dataframe.getInts("voltage_regulator_on");
this.busOrBusbarSections = dataframe.getStrings("bus_or_busbar_section_id");
this.regulatingElements = dataframe.getStrings("regulating_element_id");
}

VscConverterStationAdder createAdder(Network network, int row) {
Expand All @@ -74,6 +78,8 @@ VscConverterStationAdder createAdder(Network network, int row) {
applyIfPresent(targetV, row, adder::setVoltageSetpoint);
applyIfPresent(targetQ, row, adder::setReactivePowerSetpoint);
applyBooleanIfPresent(voltageRegulatorOn, row, adder::setVoltageRegulatorOn);
applyIfPresent(regulatingElements, row, elementId -> NetworkUtil
.setRegulatingTerminal(adder::setRegulatingTerminal, network, elementId));
return adder;
}
}
Expand Down
16 changes: 16 additions & 0 deletions java/src/main/java/com/powsybl/python/network/NetworkUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -217,4 +219,18 @@ public static Stream<ConnectablePositionFeederData> getFeeders(Network network)
return feeders.build();
}

public static void setRegulatingTerminal(Consumer<Terminal> adder, Network network, String elementId) {
Identifiable<?> injection = network.getIdentifiable(elementId);
if (injection instanceof Injection<?>) {
adder.accept(((Injection<?>) injection).getTerminal());
} else {
throw new UnsupportedOperationException("Cannot set regulated element to " + elementId +
": the regulated element may only be a busbar section or an injection.");
}
}

public static String getRegulatedElementId(Supplier<Terminal> regulatingTerminalGetter) {
Terminal terminal = regulatingTerminalGetter.get();
return terminal.getConnectable() != null ? terminal.getConnectable().getId() : null;
}
}
11 changes: 5 additions & 6 deletions tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ def test_update_generators_data_frame():
generators = n.get_generators()
assert 607 == generators['target_p']['GEN']
assert generators['voltage_regulator_on']['GEN']
assert '' == generators['regulated_element_id']['GEN']
assert 'GEN' == generators['regulated_element_id']['GEN']
generators2 = pd.DataFrame(data=[[608.0, 302.0, 25.0, False]],
columns=['target_p', 'target_q', 'target_v', 'voltage_regulator_on'], index=['GEN'])
n.update_generators(generators2)
Expand All @@ -587,13 +587,12 @@ def test_regulated_terminal_node_breaker():
def test_regulated_terminal_bus_breaker():
n = pp.network.create_eurostag_tutorial_example1_network()
generators = n.get_generators()
assert '' == generators['regulated_element_id']['GEN']

assert 'GEN' == generators['regulated_element_id']['GEN']
with pytest.raises(pp.PyPowsyblError):
n.update_generators(id='GEN', regulated_element_id='NHV1')
with pytest.raises(pp.PyPowsyblError):
n.update_generators(id='GEN', regulated_element_id='LOAD')

n.update_generators(id='GEN', regulated_element_id='LOAD')
generators = n.get_generators()
assert 'LOAD' == generators['regulated_element_id']['GEN']

def test_update_unknown_data():
n = pp.network.create_eurostag_tutorial_example1_network()
Expand Down
10 changes: 8 additions & 2 deletions tests/test_network_elements_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ def test_create_network_and_run_loadflow():

generators = pd.DataFrame.from_records(index='id', data=[
{'voltage_level_id': 'VL1', 'id': 'GEN', 'bus_id': 'B1', 'target_p': 100, 'min_p': 0, 'max_p': 200,
'target_v': 400, 'voltage_regulator_on': True}
'target_v': 400, 'voltage_regulator_on': True, 'regulating_element_id': 'LOAD'}
])
n.create_generators(generators)

Expand All @@ -562,6 +562,9 @@ def test_create_network_and_run_loadflow():
assert line.p1 == pytest.approx(100, abs=1e-1)
assert line.q1 == pytest.approx(9.7, abs=1e-1)

generator = n.get_generators().loc['GEN']
assert generator.regulated_element_id == 'LOAD'


def test_create_node_breaker_network_and_run_loadflow():
n = pn.create_empty()
Expand Down Expand Up @@ -605,7 +608,7 @@ def test_create_node_breaker_network_and_run_loadflow():

generators = pd.DataFrame.from_records(index='id', data=[
{'voltage_level_id': 'VL1', 'id': 'GEN', 'node': 3, 'target_p': 100, 'min_p': 0, 'max_p': 200,
'target_v': 400, 'voltage_regulator_on': True}
'target_v': 400, 'voltage_regulator_on': True, 'regulating_element_id': 'LOAD'}
])
n.create_generators(generators)

Expand All @@ -618,6 +621,9 @@ def test_create_node_breaker_network_and_run_loadflow():
assert line.p1 == pytest.approx(100, abs=1e-1)
assert line.q1 == pytest.approx(9.7, abs=1e-1)

generator = n.get_generators().loc['GEN']
assert generator.regulated_element_id == 'LOAD'


def test_create_limits():
net = pn.create_eurostag_tutorial_example1_network()
Expand Down
Loading

0 comments on commit a9c7efd

Please sign in to comment.