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

Adding dangling line's generation part mapping #821

Merged
merged 19 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions cpp/pypowsybl-cpp/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ PYBIND11_MODULE(_pypowsybl, m) {
.value("NON_LINEAR_SHUNT_COMPENSATOR_SECTION", element_type::NON_LINEAR_SHUNT_COMPENSATOR_SECTION)
.value("LINEAR_SHUNT_COMPENSATOR_SECTION", element_type::LINEAR_SHUNT_COMPENSATOR_SECTION)
.value("DANGLING_LINE", element_type::DANGLING_LINE)
.value("DANGLING_LINE_GENERATION", element_type::DANGLING_LINE_GENERATION)
.value("TIE_LINE", element_type::TIE_LINE)
.value("LCC_CONVERTER_STATION", element_type::LCC_CONVERTER_STATION)
.value("VSC_CONVERTER_STATION", element_type::VSC_CONVERTER_STATION)
Expand Down
1 change: 1 addition & 0 deletions cpp/pypowsybl-java/powsybl-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ typedef enum {
NON_LINEAR_SHUNT_COMPENSATOR_SECTION,
LINEAR_SHUNT_COMPENSATOR_SECTION,
DANGLING_LINE,
DANGLING_LINE_GENERATION,
TIE_LINE,
LCC_CONVERTER_STATION,
VSC_CONVERTER_STATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public enum DataframeElementType {
NON_LINEAR_SHUNT_COMPENSATOR_SECTION,
LINEAR_SHUNT_COMPENSATOR_SECTION,
DANGLING_LINE,
DANGLING_LINE_GENERATION,
TIE_LINE,
LCC_CONVERTER_STATION,
VSC_CONVERTER_STATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ private static Map<DataframeElementType, NetworkDataframeMapper> createMappers()
mappers.put(DataframeElementType.NON_LINEAR_SHUNT_COMPENSATOR_SECTION, shuntsNonLinear());
mappers.put(DataframeElementType.LINEAR_SHUNT_COMPENSATOR_SECTION, linearShuntsSections());
mappers.put(DataframeElementType.DANGLING_LINE, danglingLines());
mappers.put(DataframeElementType.DANGLING_LINE_GENERATION, danglingLinesGeneration());
mappers.put(DataframeElementType.TIE_LINE, tieLines());
mappers.put(DataframeElementType.LCC_CONVERTER_STATION, lccs());
mappers.put(DataframeElementType.VSC_CONVERTER_STATION, vscs());
Expand Down Expand Up @@ -653,6 +654,25 @@ static NetworkDataframeMapper danglingLines() {
.build();
}

static NetworkDataframeMapper danglingLinesGeneration() {
return NetworkDataframeMapperBuilder.ofStream(network -> network.getDanglingLineStream().filter(dl -> Optional.ofNullable(dl.getGeneration()).isPresent()),
getOrThrow(Network::getDanglingLine, "Dangling line with generation"))
.stringsIndex("id", DanglingLine::getId)
.doubles("min_p", (dl, context) -> perUnitPQ(context, dl.getGeneration().getMinP()),
(dl, minP, context) -> dl.getGeneration().setMinP(unPerUnitPQ(context, minP)))
.doubles("max_p", (dl, context) -> perUnitPQ(context, dl.getGeneration().getMaxP()),
(dl, maxP, context) -> dl.getGeneration().setMaxP(unPerUnitPQ(context, maxP)))
.doubles("target_p", (dl, context) -> perUnitPQ(context, dl.getGeneration().getTargetP()),
(dl, targetP, context) -> dl.getGeneration().setTargetP(unPerUnitPQ(context, targetP)))
.doubles("target_q", (dl, context) -> perUnitPQ(context, dl.getGeneration().getTargetQ()),
(dl, targetQ, context) -> dl.getGeneration().setTargetQ(unPerUnitPQ(context, targetQ)))
.doubles("target_v", (dl, context) -> perUnitV(context, dl.getGeneration().getTargetV(), dl.getTerminal()),
(dl, targetV, context) -> dl.getGeneration().setTargetV(unPerUnitV(context, targetV, dl.getTerminal())))
.booleans("voltage_regulator_on", dl -> dl.getGeneration().isVoltageRegulationOn(),
(dl, voltageRegulatorOn) -> dl.getGeneration().setVoltageRegulationOn(voltageRegulatorOn))
.build();
}

static NetworkDataframeMapper tieLines() {
return NetworkDataframeMapperBuilder.ofStream(Network::getTieLineStream, getOrThrow(Network::getTieLine, "Tie line"))
.stringsIndex("id", TieLine::getId)
Expand Down Expand Up @@ -1350,6 +1370,5 @@ private static Stream<Pair<Area, AreaBoundary>> areaBoundariesData(Network netwo
.flatMap(area -> area.getAreaBoundaryStream()
.map(areaBoundary -> Pair.of(area, areaBoundary)));
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,32 @@
*/
package com.powsybl.dataframe.network.adders;

import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.dataframe.SeriesMetadata;
import com.powsybl.dataframe.update.DoubleSeries;
import com.powsybl.dataframe.update.IntSeries;
import com.powsybl.dataframe.update.StringSeries;
import com.powsybl.dataframe.update.UpdatingDataframe;
import com.powsybl.iidm.modification.topology.CreateFeederBay;
import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder;
import com.powsybl.iidm.network.DanglingLineAdder;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VoltageLevel;
import com.powsybl.iidm.network.extensions.ConnectablePosition;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.*;

import static com.powsybl.dataframe.network.adders.NetworkUtils.getVoltageLevelOrThrowWithBusOrBusbarSectionId;
import static com.powsybl.dataframe.network.adders.SeriesUtils.applyBooleanIfPresent;
import static com.powsybl.dataframe.network.adders.SeriesUtils.applyIfPresent;

/**
* @author Yichen TANG {@literal <yichen.tang at rte-france.com>}
* @author Etienne Lesot {@literal <etienne.lesot at rte-france.com>}
* @author Sylvain Leclerc {@literal <sylvain.leclerc@rte-france.com>}
*/
public class DanglingLineDataframeAdder extends AbstractSimpleAdder {
public class DanglingLineDataframeAdder implements NetworkElementAdder {

private static final List<SeriesMetadata> METADATA = List.of(
SeriesMetadata.stringIndex("id"),
Expand All @@ -46,9 +50,19 @@ public class DanglingLineDataframeAdder extends AbstractSimpleAdder {
SeriesMetadata.strings("pairing_key")
);

private static final List<SeriesMetadata> GENERATION_METADATA = List.of(
SeriesMetadata.stringIndex("id"),
SeriesMetadata.doubles("min_p"),
SeriesMetadata.doubles("max_p"),
SeriesMetadata.doubles("target_p"),
SeriesMetadata.doubles("target_q"),
SeriesMetadata.doubles("target_v"),
SeriesMetadata.booleans("voltage_regulator_on")
);

@Override
public List<List<SeriesMetadata>> getMetadata() {
return Collections.singletonList(METADATA);
return List.of(METADATA, GENERATION_METADATA);
}

private static class DanglingLineSeries extends InjectionSeries {
Expand All @@ -63,7 +77,15 @@ private static class DanglingLineSeries extends InjectionSeries {
private final StringSeries busOrBusbarSections;
private final StringSeries pairingKey;

DanglingLineSeries(UpdatingDataframe dataframe) {
private final Map<String, Integer> generationIndexes;
private final DoubleSeries minP;
private final DoubleSeries maxP;
private final DoubleSeries targetP;
private final DoubleSeries targetQ;
private final DoubleSeries targetV;
private final IntSeries voltageRegulatorOn;

DanglingLineSeries(UpdatingDataframe dataframe, UpdatingDataframe generationDataframe) {
super(dataframe);
this.voltageLevels = dataframe.getStrings("voltage_level_id");
this.p0 = dataframe.getDoubles("p0");
Expand All @@ -74,6 +96,24 @@ private static class DanglingLineSeries extends InjectionSeries {
this.b = dataframe.getDoubles("b");
this.busOrBusbarSections = dataframe.getStrings("bus_or_busbar_section_id");
this.pairingKey = dataframe.getStrings("pairing_key");

if (generationDataframe != null && generationDataframe.getRowCount() > 0) {
this.minP = generationDataframe.getDoubles("min_p");
this.maxP = generationDataframe.getDoubles("max_p");
this.targetP = generationDataframe.getDoubles("target_p");
this.targetQ = generationDataframe.getDoubles("target_q");
this.targetV = generationDataframe.getDoubles("target_v");
this.voltageRegulatorOn = generationDataframe.getInts("voltage_regulator_on");
this.generationIndexes = getGenerationIndexes(generationDataframe);
} else {
this.minP = null;
this.maxP = null;
this.targetP = null;
this.targetQ = null;
this.targetV = null;
this.voltageRegulatorOn = null;
this.generationIndexes = null;
}
}

Optional<DanglingLineAdder> createAdder(Network network, int row, boolean throwException) {
Expand All @@ -89,21 +129,91 @@ Optional<DanglingLineAdder> createAdder(Network network, int row, boolean throwE
applyIfPresent(g, row, adder::setG);
applyIfPresent(b, row, adder::setB);
applyIfPresent(pairingKey, row, adder::setPairingKey);
addGenerationIfPresent(adder, row);
return Optional.of(adder);
} else {
return Optional.empty();
}
}

private void addGenerationIfPresent(DanglingLineAdder adder, int row) {
if (generationIndexes == null) {
return;
}
String id = ids.get(row);
Integer generationRow = generationIndexes.get(id);
if (generationRow != null) {
DanglingLineAdder.GenerationAdder genAdder = adder.newGeneration();
applyIfPresent(minP, generationRow, genAdder::setMinP);
applyIfPresent(maxP, generationRow, genAdder::setMaxP);
applyIfPresent(targetP, generationRow, genAdder::setTargetP);
applyIfPresent(targetQ, generationRow, genAdder::setTargetQ);
applyIfPresent(targetV, generationRow, genAdder::setTargetV);
applyBooleanIfPresent(voltageRegulatorOn, generationRow, genAdder::setVoltageRegulationOn);
genAdder.add();
}
}

/**
* Mapping shunt ID --> index of line in dataframe
*/
private static Map<String, Integer> getGenerationIndexes(UpdatingDataframe generationDf) {
StringSeries ids = generationDf.getStrings("id");
if (ids == null) {
throw new PowsyblException("Dangling line generation dataframe: id is not set");
}
Map<String, Integer> indexes = new HashMap<>();
for (int generationIndex = 0; generationIndex < generationDf.getRowCount(); generationIndex++) {
String danglingLineId = ids.get(generationIndex);
indexes.put(danglingLineId, generationIndex);
}
return indexes;
}

void create(Network network, int row, boolean throwException) {
Optional<DanglingLineAdder> adder = createAdder(network, row, throwException);
adder.ifPresent(DanglingLineAdder::add);
}

void createWithBay(Network network, int row, UpdatingDataframe primaryDataframe, boolean throwException, ReportNode reportNode) {
Optional<DanglingLineAdder> adder = createAdder(network, row, throwException);
adder.ifPresent(presentAdder -> addWithBay(network, row, primaryDataframe, presentAdder, throwException, reportNode));
}

void addWithBay(Network network, int row, UpdatingDataframe dataframe, DanglingLineAdder adder, boolean throwException, ReportNode reportNode) {
String busOrBusbarSectionId = busOrBusbarSections.get(row);
OptionalInt injectionPositionOrder = dataframe.getIntValue("position_order", row);
ConnectablePosition.Direction direction = ConnectablePosition.Direction.valueOf(dataframe.getStringValue("direction", row).orElse("BOTTOM"));
CreateFeederBayBuilder builder = new CreateFeederBayBuilder()
.withInjectionAdder(adder)
.withBusOrBusbarSectionId(busOrBusbarSectionId)
.withInjectionDirection(direction);
if (injectionPositionOrder.isPresent()) {
builder.withInjectionPositionOrder(injectionPositionOrder.getAsInt());
}
CreateFeederBay modification = builder.build();
modification.apply(network, throwException, reportNode == null ? ReportNode.NO_OP : reportNode);
}
}

@Override
public void addElements(Network network, UpdatingDataframe dataframe, AdditionStrategy additionStrategy, boolean throwException, ReportNode reportNode) {
DanglingLineSeries series = new DanglingLineSeries(dataframe);
public void addElements(Network network, List<UpdatingDataframe> dataframes) {
UpdatingDataframe dataframe = dataframes.get(0);
UpdatingDataframe generationDataframe = dataframes.get(1);
DanglingLineSeries series = new DanglingLineSeries(dataframe, generationDataframe);
for (int row = 0; row < dataframe.getRowCount(); row++) {
Optional<DanglingLineAdder> adder = series.createAdder(network, row, throwException);
if (adder.isPresent()) {
additionStrategy.add(network, dataframe, adder.get(), row, throwException, reportNode);
}
series.create(network, row, true);
}
}

@Override
public void addElementsWithBay(Network network, List<UpdatingDataframe> dataframes, boolean throwException, ReportNode reportNode) {
UpdatingDataframe dataframe = dataframes.get(0);
UpdatingDataframe generationDataframe = dataframes.get(1);
DanglingLineSeries series = new DanglingLineSeries(dataframe, generationDataframe);
for (int row = 0; row < dataframe.getRowCount(); row++) {
series.createWithBay(network, row, dataframe, true, reportNode);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ public enum ElementType {
NON_LINEAR_SHUNT_COMPENSATOR_SECTION,
LINEAR_SHUNT_COMPENSATOR_SECTION,
DANGLING_LINE,
DANGLING_LINE_GENERATION,
TIE_LINE,
LCC_CONVERTER_STATION,
VSC_CONVERTER_STATION,
Expand Down
2 changes: 2 additions & 0 deletions java/src/main/java/com/powsybl/python/commons/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public static PyPowsyblApiHeader.ElementType convert(DataframeElementType type)
case BATTERY -> PyPowsyblApiHeader.ElementType.BATTERY;
case SHUNT_COMPENSATOR -> PyPowsyblApiHeader.ElementType.SHUNT_COMPENSATOR;
case DANGLING_LINE -> PyPowsyblApiHeader.ElementType.DANGLING_LINE;
case DANGLING_LINE_GENERATION -> PyPowsyblApiHeader.ElementType.DANGLING_LINE_GENERATION;
case TIE_LINE -> PyPowsyblApiHeader.ElementType.TIE_LINE;
case LCC_CONVERTER_STATION -> PyPowsyblApiHeader.ElementType.LCC_CONVERTER_STATION;
case VSC_CONVERTER_STATION -> PyPowsyblApiHeader.ElementType.VSC_CONVERTER_STATION;
Expand Down Expand Up @@ -239,6 +240,7 @@ public static DataframeElementType convert(PyPowsyblApiHeader.ElementType type)
case BATTERY -> DataframeElementType.BATTERY;
case SHUNT_COMPENSATOR -> DataframeElementType.SHUNT_COMPENSATOR;
case DANGLING_LINE -> DataframeElementType.DANGLING_LINE;
case DANGLING_LINE_GENERATION -> DataframeElementType.DANGLING_LINE_GENERATION;
case TIE_LINE -> DataframeElementType.TIE_LINE;
case LCC_CONVERTER_STATION -> DataframeElementType.LCC_CONVERTER_STATION;
case VSC_CONVERTER_STATION -> DataframeElementType.VSC_CONVERTER_STATION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,19 @@ void danglingLines() {
.extracting(Series::getName)
.containsExactly("id", "name", "r", "x", "g", "b", "p0", "q0", "p", "q", "i",
"boundary_p", "boundary_q", "boundary_v_mag", "boundary_v_angle",
"voltage_level_id", "bus_id", "bus_breaker_bus_id", "node", "connected",
"pairing_key", "ucte_xnode_code", "paired", "fictitious", "tie_line_id",
"selected_limits_group");
"voltage_level_id", "bus_id", "bus_breaker_bus_id", "node", "connected", "pairing_key",
"ucte_xnode_code", "paired", "fictitious", "tie_line_id", "selected_limits_group");
}

@Test
void danglingLinesGeneration() {
Network network = EurostagTutorialExample1Factory.create();
List<Series> series = createDataFrame(DANGLING_LINE_GENERATION, network);

assertThat(series)
.extracting(Series::getName)
.containsExactly("id", "min_p", "max_p", "target_p", "target_q",
"target_v", "voltage_regulator_on");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,43 @@ void danglingLine() {
addDoubleColumn(dataframe, "b", Math.pow(10, -6) * 4);
addDoubleColumn(dataframe, "p0", 102d);
addDoubleColumn(dataframe, "q0", 151d);
NetworkElementAdders.addElements(DataframeElementType.DANGLING_LINE, network, singletonList(dataframe));
var emptyGenerationDataframe = new DefaultUpdatingDataframe(0);
NetworkElementAdders.addElements(DataframeElementType.DANGLING_LINE, network, List.of(dataframe, emptyGenerationDataframe));
assertEquals(2, network.getDanglingLineCount());
}

@Test
void danglingLineWithGeneration() {
var network = DanglingLineNetworkFactory.create();
var dataframe = new DefaultUpdatingDataframe(1);
addStringColumn(dataframe, "id", "dl2");
addStringColumn(dataframe, "name", "name-dl2");
addStringColumn(dataframe, "connectable_bus_id", "BUS");
addStringColumn(dataframe, "bus_id", "BUS");
addStringColumn(dataframe, "voltage_level_id", "VL");
addDoubleColumn(dataframe, "r", 0.6d);
addDoubleColumn(dataframe, "x", 1d);
addDoubleColumn(dataframe, "g", Math.pow(10, -6));
addDoubleColumn(dataframe, "b", Math.pow(10, -6) * 4);
addDoubleColumn(dataframe, "p0", 102d);
addDoubleColumn(dataframe, "q0", 151d);

var generationDataframe = new DefaultUpdatingDataframe(1);
addStringColumn(generationDataframe, "id", "dl2");
addDoubleColumn(generationDataframe, "min_p", 0);
addDoubleColumn(generationDataframe, "max_p", 200d);
addDoubleColumn(generationDataframe, "target_p", 102d);
addDoubleColumn(generationDataframe, "target_q", 151d);
addDoubleColumn(generationDataframe, "target_v", 100d);
addIntColumn(generationDataframe, "voltage_regulator_on", 1);
NetworkElementAdders.addElements(DataframeElementType.DANGLING_LINE, network, List.of(dataframe, generationDataframe));

assertEquals(2, network.getDanglingLineCount());
DanglingLine dl = network.getDanglingLine("dl2");
assertTrue(Optional.ofNullable(dl.getGeneration()).isPresent());
assertTrue(dl.getGeneration().isVoltageRegulationOn());
}

@Test
void busbar() {
var network = HvdcTestNetwork.createBase();
Expand Down
1 change: 1 addition & 0 deletions pypowsybl/_pypowsybl.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class ElementType:
BUS_FROM_BUS_BREAKER_VIEW: ClassVar[ElementType] = ...
BUSBAR_SECTION: ClassVar[ElementType] = ...
DANGLING_LINE: ClassVar[ElementType] = ...
DANGLING_LINE_GENERATION: ClassVar[ElementType] = ...
TIE_LINE: ClassVar[ElementType] = ...
GENERATOR: ClassVar[ElementType] = ...
HVDC_LINE: ClassVar[ElementType] = ...
Expand Down
Loading
Loading