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

[SLD] add limit violation highlight #643

Merged
merged 30 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
256f30c
[SLD] add sld-overload class to equipment label
jamal-khey Sep 3, 2024
2488efc
small code improuvement
jamal-khey Sep 3, 2024
0e39dcf
small code improuvement
jamal-khey Sep 3, 2024
279d0d4
add sld-overload
jamal-khey Sep 4, 2024
5773778
fix tests
jamal-khey Sep 4, 2024
a4b2252
add test for transformer
jamal-khey Sep 5, 2024
aa5d204
remove style from text
jamal-khey Sep 5, 2024
309d81e
Merge branch 'main' into jamalkhey/add-overloadStyle
jamal-khey Sep 5, 2024
c9248bb
fix sonar issues and clean code
jamal-khey Sep 5, 2024
a80311a
clean import
jamal-khey Sep 10, 2024
c5e977e
move sld-overload class to HighlightLineStateStyleProvider.
jamal-khey Sep 13, 2024
bee0d5c
move overload style to HightlightLineStateSyleProvider
jamal-khey Sep 13, 2024
621570f
fix tests , updates svg
jamal-khey Sep 16, 2024
9768bfd
add current violation to busbar section
jamal-khey Sep 17, 2024
2cdf4ad
fix sonar issues
jamal-khey Sep 18, 2024
9899c4a
Merge branch 'main' into jamalkhey/add-overloadStyle
jamal-khey Sep 18, 2024
5a2f24f
Restore AbstractTestCase (debugSvgFiles = true should not be committed)
So-Fras Sep 19, 2024
35f3c7c
rename remaining overload to limit-exceeded
jamal-khey Sep 19, 2024
9f1f4bd
Revert "rename remaining overload to limit-exceeded"
jamal-khey Sep 19, 2024
94b2598
add basic limit detection
jamal-khey Sep 22, 2024
e2d2f1e
fix missing sub part of a branch
jamal-khey Sep 23, 2024
0c294d0
undo useless changes
jamal-khey Sep 24, 2024
834cdcc
reduce the diff with main
jamal-khey Sep 24, 2024
ce47d1c
fixing review comments
jamal-khey Oct 10, 2024
08cd97e
Merge branch 'main' into jamalkhey/add-overloadStyle
jamal-khey Oct 10, 2024
0abd4da
fix failing unit test
jamal-khey Oct 10, 2024
d3571be
do not extends overload to adjacent edge
jamal-khey Oct 10, 2024
705c6cf
Merge branch 'main' into jamalkhey/add-overloadStyle
jamal-khey Oct 10, 2024
894bb27
fix remaning review comments
jamal-khey Oct 10, 2024
78432bb
rename OverloadHighlightStyleProvider to LimitHighlightStyleProvider
jamal-khey Oct 10, 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 @@ -25,6 +25,9 @@ public final class StyleClassConstants {
public static final String INTERN_CELL = STYLE_PREFIX + "intern-cell";
public static final String EXTERN_CELL = STYLE_PREFIX + "extern-cell";
public static final String FICTITIOUS_NODE_STYLE_CLASS = STYLE_PREFIX + "fictitious";
public static final String OVERLOAD_STYLE_CLASS = STYLE_PREFIX + "overload";
public static final String VL_OVERVOLTAGE_CLASS = STYLE_PREFIX + "vl-overvoltage";
public static final String VL_UNDERVOLTAGE_CLASS = STYLE_PREFIX + "vl-undervoltage";
public static final String NODE_INFOS = STYLE_PREFIX + "node-infos";
public static final String FRAME_CLASS = STYLE_PREFIX + "frame";
public static final String TOP_FEEDER = STYLE_PREFIX + "top-feeder";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.powsybl.sld.svg.styles.iidm;
flo-dup marked this conversation as resolved.
Show resolved Hide resolved

import com.powsybl.iidm.network.*;
import com.powsybl.sld.library.ComponentLibrary;
import com.powsybl.sld.model.graphs.Graph;
import com.powsybl.sld.model.graphs.VoltageLevelGraph;
import com.powsybl.sld.model.nodes.*;
import com.powsybl.sld.model.nodes.feeders.FeederWithSides;
import com.powsybl.sld.svg.styles.EmptyStyleProvider;
import java.util.*;

import static com.powsybl.sld.svg.styles.StyleClassConstants.*;

/**
* @author Jamal KHEYYAD {@literal <jamal.kheyyad at rte-international.com>}
*/
public class LimitHighlightStyleProvider extends EmptyStyleProvider {
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
Network network;
flo-dup marked this conversation as resolved.
Show resolved Hide resolved

public LimitHighlightStyleProvider(Network network) {
this.network = network;
}

@Override
public List<String> getEdgeStyles(Graph graph, Edge edge) {
Optional<String> overloadStyle = getOverloadStyle(edge);
return overloadStyle.map(Collections::singletonList).orElse(Collections.emptyList());
}

private Optional<String> getOverloadStyle(Edge edge) {
List<Node> nodes = edge.getNodes();
for (Node node : nodes) {
if (node instanceof FeederNode feederNode) {
return getHighlightFeederStateStyle(feederNode);
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
} else if (node instanceof ConnectivityNode connectivityNode && hasOverloadedAdjacentNode(connectivityNode)) {
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
return Optional.of(OVERLOAD_STYLE_CLASS);
}
}
return Optional.empty();
}

boolean hasOverloadedAdjacentNode(ConnectivityNode connectivityNode) {
return connectivityNode.getAdjacentNodes().stream().anyMatch(node -> {
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
if (node instanceof FeederNode feederNode) {
return isOverloaded(feederNode);
}
return false;
});
}

protected Optional<String> getHighlightFeederStateStyle(FeederNode n) {
if (isOverloaded(n)) {
return Optional.of(OVERLOAD_STYLE_CLASS);
}
return Optional.empty();
}

private boolean isOverloaded(FeederNode n) {
if (!(n.getFeeder() instanceof FeederWithSides)) {
return false;
}
Connectable<?> connectable = network.getConnectable(n.getEquipmentId());
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
if (connectable instanceof Branch<?> branch && branch.isOverloaded()) {
return true;
} else {
return connectable instanceof ThreeWindingsTransformer transformer && transformer.isOverloaded();
}
}

@Override
public List<String> getNodeStyles(VoltageLevelGraph graph, Node node, ComponentLibrary componentLibrary, boolean showInternalNodes) {
if (!(node instanceof BusNode busNode)) {
return Collections.emptyList();
}
List<String> styles = new ArrayList<>();
BusbarSection busbarSection = this.network.getBusbarSection(busNode.getEquipmentId());
if (busbarSection != null) {

if (busbarSection.getV() > busbarSection.getTerminal().getVoltageLevel().getHighVoltageLimit()) {
styles.add(VL_OVERVOLTAGE_CLASS);
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
} else if (busbarSection.getV() < busbarSection.getTerminal().getVoltageLevel().getLowVoltageLimit()) {
styles.add(VL_UNDERVOLTAGE_CLASS);
}
}
return styles;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,57 @@
.sld-arrow-animation-low-speed { --sld-arrow-animation-parameters: 3s infinite linear }
.sld-arrow-animation-average-speed { --sld-arrow-animation-parameters: 2s infinite linear }
.sld-arrow-animation-high-speed { --sld-arrow-animation-parameters: 1s infinite linear }

:root {
--sld-overload-color: #ffeb3b; /* Yellow for overload */
--sld-overvoltage-color: #5a0101; /* Red for overvoltage */
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
--sld-undervoltage-color: #0000ff; /* Blue for undervoltage */
}
flo-dup marked this conversation as resolved.
Show resolved Hide resolved

@keyframes sld-overload-blink-animation {
0%,
80%,
100% {
stroke-width: 1;
}
40% {
stroke: var(--sld-overload-color);
stroke-width: 2;
}
}

@keyframes sld-overvoltage-blink-animation {
0%,
80%,
100% {
stroke-width: 1;
}
40% {
stroke: var(--sld-overvoltage-color);
stroke-width: 2;
}
}

@keyframes sld-undervoltage-blink-animation {
0%,
80%,
100% {
stroke-width: 1;
}
40% {
stroke: var(--sld-undervoltage-color);
stroke-width: 2;
}
}

.sld-overload {
animation: sld-overload-blink-animation 3s infinite;
}

.sld-vl-overvoltage {
animation: sld-overvoltage-blink-animation 3s infinite;
}

.sld-vl-undervoltage {
animation: sld-undervoltage-blink-animation 3s infinite;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.sld.iidm;

import com.powsybl.diagram.test.Networks;
import com.powsybl.iidm.network.test.ThreeWindingsTransformerNetworkFactory;
import com.powsybl.sld.builders.NetworkGraphBuilder;
import com.powsybl.sld.model.graphs.VoltageLevelGraph;
import com.powsybl.sld.svg.styles.AnimatedFeederInfoStyleProvider;
import com.powsybl.sld.svg.styles.StyleProvider;
import com.powsybl.sld.svg.styles.StyleProvidersList;
import com.powsybl.sld.svg.styles.iidm.LimitHighlightStyleProvider;
import com.powsybl.sld.svg.styles.iidm.TopologicalStyleProvider;
import org.junit.jupiter.api.Test;

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

/**
* @author Jamal KHEYYAD {@literal <jamal.kheyyad at rte-international.com>}
*/
class TestCaseLimitViolation extends AbstractTestCaseIidm {

@Override
public void setUp() {
// initialization of networks and graph builder done in each test
}

@Override
public StyleProvider getDefaultDiagramStyleProvider() {
return new StyleProvidersList(new TopologicalStyleProvider(network), new LimitHighlightStyleProvider(network), new AnimatedFeederInfoStyleProvider(500, 1000));
}

@Test
void testLineOverLoad() {
network = Networks.createNetworkWithLine();
network.getVoltageLevel("VoltageLevel1")
.setHighVoltageLimit(400)
.setLowVoltageLimit(390);
network.getLine("Line").newCurrentLimits1().setPermanentLimit(250).add();
network.getLine("Line").getTerminal1().setP(101).setQ(150).getBusView().getBus().setV(390);
graphBuilder = new NetworkGraphBuilder(network);
VoltageLevelGraph g = graphBuilder.buildVoltageLevelGraph("VoltageLevel1");
voltageLevelGraphLayout(g);
assertEquals(toString("/TestLineFeederInfoOverLoad.svg"), toSVG(g, "/TestLineFeederInfoOverLoad.svg"));
}

@Test
void test2WTOverLoad() {
network = Networks.createNetworkWithTwoWindingsTransformer();
network.getTwoWindingsTransformer("Transformer").newCurrentLimits2().setPermanentLimit(250).add();
network.getTwoWindingsTransformer("Transformer").getTerminal2().setP(101).setQ(150).getBusView().getBus().setV(390);
graphBuilder = new NetworkGraphBuilder(network);
VoltageLevelGraph g = graphBuilder.buildVoltageLevelGraph("VoltageLevel1");
voltageLevelGraphLayout(g);
assertEquals(toString("/TestTransformerFeederInfoOverLoad.svg"), toSVG(g, "/TestTransformerFeederInfoOverLoad.svg"));
}

@Test
void test3WTOverLoad() {
network = ThreeWindingsTransformerNetworkFactory.create();
network.getThreeWindingsTransformer("3WT").getLeg1().newCurrentLimits().setPermanentLimit(250).add();
network.getThreeWindingsTransformer("3WT").getLeg2().newCurrentLimits().setPermanentLimit(250).add();
network.getThreeWindingsTransformer("3WT").getLeg3().newCurrentLimits().setPermanentLimit(250).add();
network.getThreeWindingsTransformer("3WT").getLeg1().getTerminal().setP(-2800.0).setQ(400.0);
network.getThreeWindingsTransformer("3WT").getLeg2().getTerminal().setP(1400.0).setQ(400.0);
network.getThreeWindingsTransformer("3WT").getLeg3().getTerminal().setP(1400.0).setQ(400.0);
graphBuilder = new NetworkGraphBuilder(network);
// Build substation graph and run layout
VoltageLevelGraph g = graphBuilder.buildVoltageLevelGraph("VL_132");
voltageLevelGraphLayout(g);

assertEquals(toString("/Test3WTFeederInfoOverLoad.svg"), toSVG(g, "/Test3WTFeederInfoOverLoad.svg"));
}

@Test
void testBusOverVoltageLimitViolation() {
network = Networks.createComplexExternCellOnFourSections();

network.getBusbarSection("bbs3").getTerminal().getBusView().getBus().setV(390);
network.getBusbarSection("bbs3").getTerminal().getVoltageLevel().setHighVoltageLimit(1);
network.getBusbarSection("bbs3").getTerminal().getVoltageLevel().setLowVoltageLimit(0);

graphBuilder = new NetworkGraphBuilder(network);
VoltageLevelGraph g = graphBuilder.buildVoltageLevelGraph("vl");
voltageLevelGraphLayout(g);
assertEquals(toString("/TestBusBarOverVoltageLimitHightlight.svg"), toSVG(g, "/TestBusBarOverVoltageLimitHightlight.svg"));
}

@Test
void testBusUnderVoltageLimitViolation() {
network = Networks.createComplexExternCellOnFourSections();

network.getBusbarSection("bbs3").getTerminal().getBusView().getBus().setV(200);
network.getBusbarSection("bbs3").getTerminal().getVoltageLevel().setHighVoltageLimit(400);
network.getBusbarSection("bbs3").getTerminal().getVoltageLevel().setLowVoltageLimit(390);

graphBuilder = new NetworkGraphBuilder(network);
VoltageLevelGraph g = graphBuilder.buildVoltageLevelGraph("vl");
voltageLevelGraphLayout(g);
assertEquals(toString("/TestBusBarUnderVoltageLimitHightlight.svg"), toSVG(g, "/TestBusBarUnderVoltageLimitHightlight.svg"));
}

}
Loading