diff --git a/CHANGELOG.md b/CHANGELOG.md index 955e77377..553b4c7f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated dependabot workflow and added CODEOWNERS [#1328](https://github.com/ie3-institute/PowerSystemDataModel/issues/1328) - Extend azimuth angle range to [-180°, 180°] for PV inputs [#1330](https://github.com/ie3-institute/PowerSystemDataModel/issues/1330) - Improved error messages when reading and validating an invalid grid [#1354](https://github.com/ie3-institute/PowerSystemDataModel/issues/1354) +- Changed `SubgridContainer` to represent galvanically seperated grids [#1226](https://github.com/ie3-institute/PowerSystemDataModel/issues/1226) ## [7.0.0] - 2025-05-08 diff --git a/docs/readthedocs/_static/figures/transformerWithSwitchGear.png b/docs/readthedocs/_static/figures/transformerWithSwitchGear.png index 310ccf99f..0ad8468fc 100644 Binary files a/docs/readthedocs/_static/figures/transformerWithSwitchGear.png and b/docs/readthedocs/_static/figures/transformerWithSwitchGear.png differ diff --git a/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex b/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex index 8ca4ed98a..ac2d44160 100644 --- a/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex +++ b/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex @@ -159,9 +159,9 @@ \begin{tikzpicture} % === Anschlüsse === \node[circle, draw = tuGreen, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_a) at (0,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){}; \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_e) at (62.5mm,0){}; \draw (port_a.west) -- ++(-3mm, -1mm) -- ++(0mm, -2mm) edge[densely dotted] ++(0mm, -1.8mm); @@ -176,9 +176,9 @@ \draw (port_d.east) -- (winding_a.west) (winding_b.east) -- (port_e.west); \node[tuGreen, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_a.south) {A \\ \SI{110}{\kV} \\ 1}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 2}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 2}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 2}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 1}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 1}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 1}; \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_e.south) {E \\ \SI{10}{\kV} \\ 2}; \end{tikzpicture} \end{document} \ No newline at end of file diff --git a/docs/readthedocs/models/input/grid/gridcontainer.md b/docs/readthedocs/models/input/grid/gridcontainer.md index 24f8e66c4..9c8eebd44 100644 --- a/docs/readthedocs/models/input/grid/gridcontainer.md +++ b/docs/readthedocs/models/input/grid/gridcontainer.md @@ -24,14 +24,11 @@ and their higher voltage coupling point. Let's shed a more detailed light on the boundaries of a sub grid as of our definition. This especially is important, if the switchgear of the transformer is modeled in detail. -We defined, that all nodes in upstream direction of the transformer, that are connected by switches *only* (therefore -are within the switchgear) are counted towards the inferior sub grid structure (here "2"), although they belong to a -different voltage level. -This decision is taken, because we assume, that the interest to operate on the given switchgear will most likely be -placed in the inferior grid structure. - -The "real" coupling node A is not comprised in the sub grids node collection, but obviously has reference through the -switch between nodes A and B. +We defined, that all nodes in upstream direction of the transformer, including those, which are within the switchgear are +counted towards the superior sub grid structure (here "1"), because they belong to a different voltage level. +If a switchgear should be operated by the inferior grid, one can set the operator, that is used in the inferior grid, for +the switchgear. This can be necessary, if we assume, that the interest to operate on the given switchgear will most likely +be placed in the inferior grid structure. A synoptic overview of both classes' attributes is given here: diff --git a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java index 5033221a2..522dfeaa4 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java @@ -426,41 +426,11 @@ public static GraphicElements filterForSubnet(GraphicElements input, int subnet) */ public static VoltageLevel determinePredominantVoltLvl(RawGridElements rawGrid, int subnet) throws InvalidGridException { - /* Exclude all nodes, that are at the high voltage side of the transformer */ - Set gridNodes = new HashSet<>(rawGrid.getNodes()); - gridNodes.removeAll( - /* Remove all nodes, that are upstream of transformers, this comprises all those, that are connected by - * switches */ - rawGrid.getTransformer2Ws().stream() - .flatMap( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream()) - .collect(Collectors.toSet())); - gridNodes.removeAll( - rawGrid.getTransformer3Ws().stream() - .flatMap( - transformer -> { - if (transformer.getNodeA().getSubnet() == subnet) - return Stream.of(transformer.getNodeB(), transformer.getNodeC()); - else if (transformer.getNodeB().getSubnet() == subnet) - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeC(), transformer.getNodeInternal())); - else - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeB(), transformer.getNodeInternal())); - }) - .collect(Collectors.toSet())); - /* Build a mapping, which voltage level appears how often */ Map voltageLevelCount = - gridNodes.stream() - .map(NodeInput::getVoltLvl) - .collect(Collectors.groupingBy(voltLvl -> voltLvl, Collectors.counting())); + rawGrid.getNodes().stream() + .filter(n -> n.getSubnet() == subnet) + .collect(Collectors.groupingBy(NodeInput::getVoltLvl, Collectors.counting())); /* At this point only one voltage level should be apparent */ int amountOfVoltLvl = voltageLevelCount.size(); @@ -677,14 +647,8 @@ private static TransformerSubGridContainers getSubGridContainers( RawGridElements rawGridElements, Map subGrids) throws TopologyException { - /* Get the sub grid container at port A - travel upstream as long as nodes are connected - * _only_ by switches */ - NodeInput topNode = traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements).getLast(); - if (Objects.isNull(topNode)) - throw new TopologyException( - "Cannot find most upstream node of transformer '" + transformer + "'"); - - SubGridContainer containerA = subGrids.get(topNode.getSubnet()); + /* Get the sub grid container at port A */ + SubGridContainer containerA = subGrids.get(transformer.getNodeA().getSubnet()); /* Get the sub grid container at port B */ SubGridContainer containerB = subGrids.get(transformer.getNodeB().getSubnet()); @@ -696,81 +660,6 @@ private static TransformerSubGridContainers getSubGridContainers( } else return new TransformerSubGridContainers(containerA, containerB); } - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or is connected to any other type of connector (e.g. - * lines, transformers) and therefore leads to other parts of a "real" grid. If the starting node - * is not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param rawGridElements Elements of the pure grid structure. - * @return The end node of the switch chain - */ - public static LinkedList traverseAlongSwitchChain( - NodeInput startNode, RawGridElements rawGridElements) { - Set possibleJunctions = - Stream.concat( - Stream.concat( - rawGridElements.getLines().parallelStream(), - rawGridElements.getTransformer2Ws().parallelStream()), - rawGridElements.getTransformer3Ws().parallelStream()) - .flatMap(connector -> connector.allNodes().parallelStream()) - .collect(Collectors.toSet()); - return traverseAlongSwitchChain(startNode, rawGridElements.getSwitches(), possibleJunctions); - } - - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or part of the provided node set. If the starting node is - * not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param switches Set of available switches - * @param possibleJunctions Set of nodes that denote possible junctions to "real" grid - * @return The end node of the switch chain - */ - private static LinkedList traverseAlongSwitchChain( - NodeInput startNode, Set switches, Set possibleJunctions) { - LinkedList traveledNodes = new LinkedList<>(); - traveledNodes.addFirst(startNode); - - /* Get the switch, that is connected to the starting node and determine the next node */ - List nextSwitches = - switches.stream().filter(switcher -> switcher.allNodes().contains(startNode)).toList(); - switch (nextSwitches.size()) { - case 0: - /* No further switch found -> Return the starting node */ - break; - case 1: - /* One next switch has been found -> Travel in this direction */ - SwitchInput nextSwitch = nextSwitches.get(0); - Optional candidateNodes = - nextSwitch.allNodes().stream().filter(node -> node != startNode).findFirst(); - NodeInput nextNode = - candidateNodes.orElseThrow( - () -> - new IllegalArgumentException( - "There is no further node available at switch " + nextSwitch)); - if (possibleJunctions.contains(nextNode)) { - /* This is a junction, leading to another Connector than a switch */ - traveledNodes.addLast(nextNode); - } else { - /* Add the traveled nodes to the nodes to be excluded, to avoid endless loops in cyclic switch topologies */ - HashSet newNodesToExclude = new HashSet<>(possibleJunctions); - newNodesToExclude.add(nextNode); - HashSet newSwitches = new HashSet<>(switches); - newSwitches.remove(nextSwitch); - traveledNodes.addAll(traverseAlongSwitchChain(nextNode, newSwitches, newNodesToExclude)); - } - break; - default: - throw new IllegalArgumentException( - "Cannot traverse along switch chain, as there is a junction included at node " - + startNode); - } - return traveledNodes; - } - /** * Combines a given collection of sub grid containers to a joint model. If the single models do * not fit together, exceptions are thrown. diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java index 471c83567..0c4ecac7a 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java @@ -20,7 +20,6 @@ import edu.ie3.datamodel.models.input.container.*; import edu.ie3.datamodel.models.input.graphics.GraphicInput; import edu.ie3.datamodel.models.input.system.SystemParticipantInput; -import edu.ie3.datamodel.utils.ContainerUtils; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; import edu.ie3.datamodel.utils.Try.Success; @@ -28,7 +27,6 @@ import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.jgrapht.Graph; import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.graph.DefaultEdge; @@ -140,26 +138,12 @@ private GridContainerValidationUtils() { exceptions.addAll(ConnectorValidationUtils.check(transformer)); }); - /* Checking switches - * Because of the fact, that a transformer with switch gear in "upstream" direction has its corresponding node in - * upper grid connected to a switch, instead of to the transformer directly: Collect all nodes at the end of the - * upstream switch chain and add them to the set of allowed nodes */ - HashSet validSwitchNodes = new HashSet<>(nodes); - validSwitchNodes.addAll( - Stream.of(rawGridElements.getTransformer2Ws(), rawGridElements.getTransformer2Ws()) - .flatMap(Set::stream) - .parallel() - .map( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements) - .getLast()) - .toList()); - + /* Checking switches */ rawGridElements .getSwitches() .forEach( switcher -> { - exceptions.add(checkNodeAvailability(switcher, validSwitchNodes)); + exceptions.add(checkNodeAvailability(switcher, nodes)); exceptions.addAll(ConnectorValidationUtils.check(switcher)); }); diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java index 6d664aba1..80006953b 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java @@ -5,12 +5,12 @@ */ package edu.ie3.datamodel.utils.validation; -import edu.ie3.datamodel.exceptions.FailedValidationException; -import edu.ie3.datamodel.exceptions.InvalidEntityException; -import edu.ie3.datamodel.exceptions.UnsafeEntityException; -import edu.ie3.datamodel.exceptions.ValidationException; +import edu.ie3.datamodel.exceptions.*; import edu.ie3.datamodel.models.UniqueEntity; -import edu.ie3.datamodel.models.input.*; +import edu.ie3.datamodel.models.input.AssetInput; +import edu.ie3.datamodel.models.input.AssetTypeInput; +import edu.ie3.datamodel.models.input.MeasurementUnitInput; +import edu.ie3.datamodel.models.input.NodeInput; import edu.ie3.datamodel.models.input.connector.ConnectorInput; import edu.ie3.datamodel.models.input.connector.type.LineTypeInput; import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput; @@ -22,11 +22,8 @@ import edu.ie3.datamodel.models.input.system.type.SystemParticipantTypeInput; import edu.ie3.datamodel.models.input.thermal.ThermalUnitInput; import edu.ie3.datamodel.utils.Try; -import edu.ie3.datamodel.utils.Try.Failure; -import edu.ie3.datamodel.utils.Try.Success; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import edu.ie3.datamodel.utils.Try.*; +import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.measure.Quantity; @@ -160,8 +157,6 @@ else if (ThermalUnitInput.class.isAssignableFrom(assetInput.getClass())) exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput)); else if (ThermalGrid.class.isAssignableFrom(assetInput.getClass())) exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput)); - else if (EmInput.class.isAssignableFrom(assetInput.getClass())) - exceptions.addAll(EnergyManagementValidationUtils.check((EmInput) assetInput)); else { logNotImplemented(assetInput); } diff --git a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy index c07ff0d54..660603fe9 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy @@ -553,176 +553,7 @@ class ContainerUtilsTest extends Specification { * - filtering of system participants can be tested * - filtering of graphic elements can be tested */ - def "Traversing along a simple switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - expected.addLast(nodeD) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a switch chain with intermediate junction returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - possibleJunctions.add(nodeC) - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a non existing switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - - def switches = new HashSet() - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a cyclic switch chain throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCA = Mock(SwitchInput) - switchCA.getNodeA() >> nodeC - switchCA.getNodeB() >> nodeA - switchCA.allNodes() >> List.of(nodeC, nodeA) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCA) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeA'" - } - - def "Traversing along a switch chain with switch junction throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchBD = Mock(SwitchInput) - switchBD.getNodeA() >> nodeB - switchBD.getNodeB() >> nodeD - switchBD.allNodes() >> List.of(nodeB, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchBD) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeB'" - } - - def "Determining the surrounding sub grid containers of a two winding transformer w/o switchgear works fine"() { + def "Determining the surrounding sub grid containers of a two winding transformer works fine"() { given: def nodeD = Mock(NodeInput) nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") @@ -754,66 +585,4 @@ class ContainerUtilsTest extends Specification { then: actual == expected } - - def "Determining the surrounding sub grid containers of a two winding transformer w/ switchgear works fine"() { - given: - def nodeA = Mock(NodeInput) - nodeA.getUuid() >> UUID.fromString("a37b2501-70c5-479f-92f9-d5b0e4628b2b") - nodeA.getSubnet() >> 1 - def nodeB = Mock(NodeInput) - nodeB.getUuid() >> UUID.fromString("8361b082-9d4c-4c54-97d0-2df9ac35333c") - nodeB.getSubnet() >> 2 - def nodeC = Mock(NodeInput) - nodeC.getUuid() >> UUID.fromString("b9e4f16b-0317-4794-9f53-339db45a2092") - nodeC.getSubnet() >> 2 - def nodeD = Mock(NodeInput) - nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") - nodeD.getSubnet() >> 2 - def nodeE = Mock(NodeInput) - nodeE.getUuid() >> UUID.fromString("5d4107b2-385b-40fe-a668-19414bf45d9d") - nodeE.getSubnet() >> 2 - - def transformer = Mock(Transformer2WInput) - transformer.getUuid() >> UUID.fromString("ddcdd72a-5f97-4bef-913b-d32d31216e27") - transformer.getNodeA() >> nodeD - transformer.getNodeB() >> nodeE - transformer.allNodes() >> List.of(nodeD, nodeE) - - def switchAB = Mock(SwitchInput) - switchAB.getUuid() >> UUID.fromString("5fcb8705-1436-4fbe-97b3-d2dcaf6a783b") - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getUuid() >> UUID.fromString("4ca81b0b-e06d-408e-a991-de140f4e229b") - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getUuid() >> UUID.fromString("92ce075e-9e3b-4ee6-89b6-19e6372fba01") - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def rawGridElements = new RawGridElements([ - nodeA, - nodeB, - nodeC, - nodeD, - nodeE, - transformer, - switchAB, - switchBC, - switchCD - ]) - - def subGrid1 = Mock(SubGridContainer) - def subGrid2 = Mock(SubGridContainer) - def subGridMapping = [ - 1: subGrid1, - 2: subGrid2 - ] - - def expected = new ContainerUtils.TransformerSubGridContainers(subGrid1, subGrid2) - - when: - def actual = ContainerUtils.getSubGridContainers(transformer, rawGridElements, subGridMapping) - - then: - actual == expected - } }