Skip to content

Commit 2909188

Browse files
Merge pull request #1366 from ie3-institute/ms/#1226-change-SubgridContainer-to-be-in-line-with-the-galvanical-seperation
Changed `SubgridContainer` to represent galvanically seperated grids
2 parents 40ca41a + 829e37b commit 2909188

File tree

8 files changed

+27
-392
lines changed

8 files changed

+27
-392
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- Updated dependabot workflow and added CODEOWNERS [#1328](https://github.com/ie3-institute/PowerSystemDataModel/issues/1328)
1919
- Extend azimuth angle range to [-180°, 180°] for PV inputs [#1330](https://github.com/ie3-institute/PowerSystemDataModel/issues/1330)
2020
- Improved error messages when reading and validating an invalid grid [#1354](https://github.com/ie3-institute/PowerSystemDataModel/issues/1354)
21+
- Changed `SubgridContainer` to represent galvanically seperated grids [#1226](https://github.com/ie3-institute/PowerSystemDataModel/issues/1226)
2122

2223
## [7.0.0] - 2025-05-08
2324

-3.02 KB
Loading

docs/readthedocs/_static/figures/transformerWithSwitchGear.tex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@
159159
\begin{tikzpicture}
160160
% === Anschlüsse ===
161161
\node[circle, draw = tuGreen, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_a) at (0,0){};
162-
\node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){};
163-
\node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){};
164-
\node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){};
162+
\node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){};
163+
\node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){};
164+
\node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){};
165165
\node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_e) at (62.5mm,0){};
166166

167167
\draw (port_a.west) -- ++(-3mm, -1mm) -- ++(0mm, -2mm) edge[densely dotted] ++(0mm, -1.8mm);
@@ -176,9 +176,9 @@
176176
\draw (port_d.east) -- (winding_a.west) (winding_b.east) -- (port_e.west);
177177

178178
\node[tuGreen, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_a.south) {A \\ \SI{110}{\kV} \\ 1};
179-
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 2};
180-
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 2};
181-
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 2};
179+
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 1};
180+
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 1};
181+
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 1};
182182
\node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_e.south) {E \\ \SI{10}{\kV} \\ 2};
183183
\end{tikzpicture}
184184
\end{document}

docs/readthedocs/models/input/grid/gridcontainer.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,11 @@ and their higher voltage coupling point.
2424

2525
Let's shed a more detailed light on the boundaries of a sub grid as of our definition.
2626
This especially is important, if the switchgear of the transformer is modeled in detail.
27-
We defined, that all nodes in upstream direction of the transformer, that are connected by switches *only* (therefore
28-
are within the switchgear) are counted towards the inferior sub grid structure (here "2"), although they belong to a
29-
different voltage level.
30-
This decision is taken, because we assume, that the interest to operate on the given switchgear will most likely be
31-
placed in the inferior grid structure.
32-
33-
The "real" coupling node A is not comprised in the sub grids node collection, but obviously has reference through the
34-
switch between nodes A and B.
27+
We defined, that all nodes in upstream direction of the transformer, including those, which are within the switchgear are
28+
counted towards the superior sub grid structure (here "1"), because they belong to a different voltage level.
29+
If a switchgear should be operated by the inferior grid, one can set the operator, that is used in the inferior grid, for
30+
the switchgear. This can be necessary, if we assume, that the interest to operate on the given switchgear will most likely
31+
be placed in the inferior grid structure.
3532

3633
A synoptic overview of both classes' attributes is given here:
3734

src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java

Lines changed: 5 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -426,41 +426,11 @@ public static GraphicElements filterForSubnet(GraphicElements input, int subnet)
426426
*/
427427
public static VoltageLevel determinePredominantVoltLvl(RawGridElements rawGrid, int subnet)
428428
throws InvalidGridException {
429-
/* Exclude all nodes, that are at the high voltage side of the transformer */
430-
Set<NodeInput> gridNodes = new HashSet<>(rawGrid.getNodes());
431-
gridNodes.removeAll(
432-
/* Remove all nodes, that are upstream of transformers, this comprises all those, that are connected by
433-
* switches */
434-
rawGrid.getTransformer2Ws().stream()
435-
.flatMap(
436-
transformer ->
437-
ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid)
438-
.stream())
439-
.collect(Collectors.toSet()));
440-
gridNodes.removeAll(
441-
rawGrid.getTransformer3Ws().stream()
442-
.flatMap(
443-
transformer -> {
444-
if (transformer.getNodeA().getSubnet() == subnet)
445-
return Stream.of(transformer.getNodeB(), transformer.getNodeC());
446-
else if (transformer.getNodeB().getSubnet() == subnet)
447-
return Stream.concat(
448-
ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid)
449-
.stream(),
450-
Stream.of(transformer.getNodeC(), transformer.getNodeInternal()));
451-
else
452-
return Stream.concat(
453-
ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid)
454-
.stream(),
455-
Stream.of(transformer.getNodeB(), transformer.getNodeInternal()));
456-
})
457-
.collect(Collectors.toSet()));
458-
459429
/* Build a mapping, which voltage level appears how often */
460430
Map<VoltageLevel, Long> voltageLevelCount =
461-
gridNodes.stream()
462-
.map(NodeInput::getVoltLvl)
463-
.collect(Collectors.groupingBy(voltLvl -> voltLvl, Collectors.counting()));
431+
rawGrid.getNodes().stream()
432+
.filter(n -> n.getSubnet() == subnet)
433+
.collect(Collectors.groupingBy(NodeInput::getVoltLvl, Collectors.counting()));
464434

465435
/* At this point only one voltage level should be apparent */
466436
int amountOfVoltLvl = voltageLevelCount.size();
@@ -677,14 +647,8 @@ private static TransformerSubGridContainers getSubGridContainers(
677647
RawGridElements rawGridElements,
678648
Map<Integer, SubGridContainer> subGrids)
679649
throws TopologyException {
680-
/* Get the sub grid container at port A - travel upstream as long as nodes are connected
681-
* _only_ by switches */
682-
NodeInput topNode = traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements).getLast();
683-
if (Objects.isNull(topNode))
684-
throw new TopologyException(
685-
"Cannot find most upstream node of transformer '" + transformer + "'");
686-
687-
SubGridContainer containerA = subGrids.get(topNode.getSubnet());
650+
/* Get the sub grid container at port A */
651+
SubGridContainer containerA = subGrids.get(transformer.getNodeA().getSubnet());
688652

689653
/* Get the sub grid container at port B */
690654
SubGridContainer containerB = subGrids.get(transformer.getNodeB().getSubnet());
@@ -696,81 +660,6 @@ private static TransformerSubGridContainers getSubGridContainers(
696660
} else return new TransformerSubGridContainers(containerA, containerB);
697661
}
698662

699-
/**
700-
* Traversing along a chain of switches and return the traveled nodes. The end thereby is defined
701-
* by a node, that either is a dead end or is connected to any other type of connector (e.g.
702-
* lines, transformers) and therefore leads to other parts of a "real" grid. If the starting node
703-
* is not part of any switch, the starting node is returned.
704-
*
705-
* @param startNode Node that is meant to be the start of the switch chain
706-
* @param rawGridElements Elements of the pure grid structure.
707-
* @return The end node of the switch chain
708-
*/
709-
public static LinkedList<NodeInput> traverseAlongSwitchChain(
710-
NodeInput startNode, RawGridElements rawGridElements) {
711-
Set<NodeInput> possibleJunctions =
712-
Stream.concat(
713-
Stream.concat(
714-
rawGridElements.getLines().parallelStream(),
715-
rawGridElements.getTransformer2Ws().parallelStream()),
716-
rawGridElements.getTransformer3Ws().parallelStream())
717-
.flatMap(connector -> connector.allNodes().parallelStream())
718-
.collect(Collectors.toSet());
719-
return traverseAlongSwitchChain(startNode, rawGridElements.getSwitches(), possibleJunctions);
720-
}
721-
722-
/**
723-
* Traversing along a chain of switches and return the traveled nodes. The end thereby is defined
724-
* by a node, that either is a dead end or part of the provided node set. If the starting node is
725-
* not part of any switch, the starting node is returned.
726-
*
727-
* @param startNode Node that is meant to be the start of the switch chain
728-
* @param switches Set of available switches
729-
* @param possibleJunctions Set of nodes that denote possible junctions to "real" grid
730-
* @return The end node of the switch chain
731-
*/
732-
private static LinkedList<NodeInput> traverseAlongSwitchChain(
733-
NodeInput startNode, Set<SwitchInput> switches, Set<NodeInput> possibleJunctions) {
734-
LinkedList<NodeInput> traveledNodes = new LinkedList<>();
735-
traveledNodes.addFirst(startNode);
736-
737-
/* Get the switch, that is connected to the starting node and determine the next node */
738-
List<SwitchInput> nextSwitches =
739-
switches.stream().filter(switcher -> switcher.allNodes().contains(startNode)).toList();
740-
switch (nextSwitches.size()) {
741-
case 0:
742-
/* No further switch found -> Return the starting node */
743-
break;
744-
case 1:
745-
/* One next switch has been found -> Travel in this direction */
746-
SwitchInput nextSwitch = nextSwitches.get(0);
747-
Optional<NodeInput> candidateNodes =
748-
nextSwitch.allNodes().stream().filter(node -> node != startNode).findFirst();
749-
NodeInput nextNode =
750-
candidateNodes.orElseThrow(
751-
() ->
752-
new IllegalArgumentException(
753-
"There is no further node available at switch " + nextSwitch));
754-
if (possibleJunctions.contains(nextNode)) {
755-
/* This is a junction, leading to another Connector than a switch */
756-
traveledNodes.addLast(nextNode);
757-
} else {
758-
/* Add the traveled nodes to the nodes to be excluded, to avoid endless loops in cyclic switch topologies */
759-
HashSet<NodeInput> newNodesToExclude = new HashSet<>(possibleJunctions);
760-
newNodesToExclude.add(nextNode);
761-
HashSet<SwitchInput> newSwitches = new HashSet<>(switches);
762-
newSwitches.remove(nextSwitch);
763-
traveledNodes.addAll(traverseAlongSwitchChain(nextNode, newSwitches, newNodesToExclude));
764-
}
765-
break;
766-
default:
767-
throw new IllegalArgumentException(
768-
"Cannot traverse along switch chain, as there is a junction included at node "
769-
+ startNode);
770-
}
771-
return traveledNodes;
772-
}
773-
774663
/**
775664
* Combines a given collection of sub grid containers to a joint model. If the single models do
776665
* not fit together, exceptions are thrown.

src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@
2020
import edu.ie3.datamodel.models.input.container.*;
2121
import edu.ie3.datamodel.models.input.graphics.GraphicInput;
2222
import edu.ie3.datamodel.models.input.system.SystemParticipantInput;
23-
import edu.ie3.datamodel.utils.ContainerUtils;
2423
import edu.ie3.datamodel.utils.Try;
2524
import edu.ie3.datamodel.utils.Try.Failure;
2625
import edu.ie3.datamodel.utils.Try.Success;
2726
import java.time.ZonedDateTime;
2827
import java.util.*;
2928
import java.util.function.Predicate;
3029
import java.util.stream.Collectors;
31-
import java.util.stream.Stream;
3230
import org.jgrapht.Graph;
3331
import org.jgrapht.alg.connectivity.ConnectivityInspector;
3432
import org.jgrapht.graph.DefaultEdge;
@@ -140,26 +138,12 @@ private GridContainerValidationUtils() {
140138
exceptions.addAll(ConnectorValidationUtils.check(transformer));
141139
});
142140

143-
/* Checking switches
144-
* Because of the fact, that a transformer with switch gear in "upstream" direction has its corresponding node in
145-
* upper grid connected to a switch, instead of to the transformer directly: Collect all nodes at the end of the
146-
* upstream switch chain and add them to the set of allowed nodes */
147-
HashSet<NodeInput> validSwitchNodes = new HashSet<>(nodes);
148-
validSwitchNodes.addAll(
149-
Stream.of(rawGridElements.getTransformer2Ws(), rawGridElements.getTransformer2Ws())
150-
.flatMap(Set::stream)
151-
.parallel()
152-
.map(
153-
transformer ->
154-
ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements)
155-
.getLast())
156-
.toList());
157-
141+
/* Checking switches */
158142
rawGridElements
159143
.getSwitches()
160144
.forEach(
161145
switcher -> {
162-
exceptions.add(checkNodeAvailability(switcher, validSwitchNodes));
146+
exceptions.add(checkNodeAvailability(switcher, nodes));
163147
exceptions.addAll(ConnectorValidationUtils.check(switcher));
164148
});
165149

src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
*/
66
package edu.ie3.datamodel.utils.validation;
77

8-
import edu.ie3.datamodel.exceptions.FailedValidationException;
9-
import edu.ie3.datamodel.exceptions.InvalidEntityException;
10-
import edu.ie3.datamodel.exceptions.UnsafeEntityException;
11-
import edu.ie3.datamodel.exceptions.ValidationException;
8+
import edu.ie3.datamodel.exceptions.*;
129
import edu.ie3.datamodel.models.UniqueEntity;
13-
import edu.ie3.datamodel.models.input.*;
10+
import edu.ie3.datamodel.models.input.AssetInput;
11+
import edu.ie3.datamodel.models.input.AssetTypeInput;
12+
import edu.ie3.datamodel.models.input.MeasurementUnitInput;
13+
import edu.ie3.datamodel.models.input.NodeInput;
1414
import edu.ie3.datamodel.models.input.connector.ConnectorInput;
1515
import edu.ie3.datamodel.models.input.connector.type.LineTypeInput;
1616
import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput;
@@ -22,11 +22,8 @@
2222
import edu.ie3.datamodel.models.input.system.type.SystemParticipantTypeInput;
2323
import edu.ie3.datamodel.models.input.thermal.ThermalUnitInput;
2424
import edu.ie3.datamodel.utils.Try;
25-
import edu.ie3.datamodel.utils.Try.Failure;
26-
import edu.ie3.datamodel.utils.Try.Success;
27-
import java.util.ArrayList;
28-
import java.util.Arrays;
29-
import java.util.List;
25+
import edu.ie3.datamodel.utils.Try.*;
26+
import java.util.*;
3027
import java.util.function.Predicate;
3128
import java.util.stream.Collectors;
3229
import javax.measure.Quantity;
@@ -160,8 +157,6 @@ else if (ThermalUnitInput.class.isAssignableFrom(assetInput.getClass()))
160157
exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput));
161158
else if (ThermalGrid.class.isAssignableFrom(assetInput.getClass()))
162159
exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput));
163-
else if (EmInput.class.isAssignableFrom(assetInput.getClass()))
164-
exceptions.addAll(EnergyManagementValidationUtils.check((EmInput) assetInput));
165160
else {
166161
logNotImplemented(assetInput);
167162
}

0 commit comments

Comments
 (0)