From 83cf8d7ee3b7fa60b1e6afd36ea83a0c698e3bdd Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Mon, 1 Sep 2025 14:45:27 +0200 Subject: [PATCH 01/12] Correctly persist EmInput entities in CsvFileSink --- CHANGELOG.md | 1 + .../edu/ie3/datamodel/io/sink/CsvFileSink.java | 18 +++++++++++++++++- .../datamodel/io/sink/CsvFileSinkTest.groovy | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5416aa3b74..6a729d9cb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed small issues in tests [#1400](https://github.com/ie3-institute/PowerSystemDataModel/issues/1400) - Fix transformer susceptance in readTheDocs to negative values [#1078](https://github.com/ie3-institute/PowerSystemDataModel/issues/1078) - Added mising fields to field validation [#1422](https://github.com/ie3-institute/PowerSystemDataModel/issues/1422) +- Correctly persist EmInput entities in CsvFileSink [#1337](https://github.com/ie3-institute/PowerSystemDataModel/issues/1337) ### Changed - Updated CI-Pipeline to run task `Deploy` and `Staging` only for `Main` [#1403](https://github.com/ie3-institute/PowerSystemDataModel/issues/1403) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 4b08d00f62..996eceab7b 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -10,6 +10,7 @@ import edu.ie3.datamodel.io.csv.BufferedCsvWriter; import edu.ie3.datamodel.io.csv.CsvFileDefinition; import edu.ie3.datamodel.io.extractor.Extractor; +import edu.ie3.datamodel.io.extractor.HasEm; import edu.ie3.datamodel.io.extractor.NestedEntity; import edu.ie3.datamodel.io.naming.FileNamingStrategy; import edu.ie3.datamodel.io.processor.ProcessorProvider; @@ -225,14 +226,29 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { .flatMap(Optional::stream) .collect(Collectors.toSet()); + // extract all EmInput entities + Set emInputs = + systemParticipants.allEntitiesAsList().stream() + .filter(Objects::nonNull) + .map(HasEm.class::cast) + .map(HasEm::getControllingEm) + .flatMap(Optional::stream) + .flatMap( + em -> + Stream.iterate( + em, Objects::nonNull, current -> current.getControllingEm().orElse(null))) + .collect(Collectors.toSet()); + // persist all entities Stream.of( rawGridElements.allEntitiesAsList(), systemParticipants.allEntitiesAsList(), graphicElements.allEntitiesAsList(), types, - operators) + operators, + emInputs) .flatMap(Collection::stream) + .collect(Collectors.toSet()) .forEach(this::persistIgnoreNested); } diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index 08b563aa4d..d84fd302ad 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -357,6 +357,7 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { testBaseFolderPath.resolve("storage_type_input.csv").toFile().exists() testBaseFolderPath.resolve("transformer_2_w_input.csv").toFile().exists() testBaseFolderPath.resolve("transformer_2_w_type_input.csv").toFile().exists() + testBaseFolderPath.resolve("em_input.csv").toFile().exists() cleanup: csvFileSink.shutdown() From 15eb11ad01ac6ec63b7c8dcd29def2608e4b50f9 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Mon, 29 Sep 2025 11:25:29 +0200 Subject: [PATCH 02/12] Add a test that reads in the persisted grid and compares it with the original grid --- .../datamodel/io/sink/CsvFileSinkTest.groovy | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index d84fd302ad..e0de935a14 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -15,6 +15,7 @@ import edu.ie3.datamodel.io.processor.input.InputEntityProcessor import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessor import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessorKey +import edu.ie3.datamodel.io.source.csv.CsvJointGridContainerSource import edu.ie3.datamodel.models.OperationTime import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.EmInput @@ -362,4 +363,29 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { cleanup: csvFileSink.shutdown() } + + def "A persisted JointGridContainer with EmInput entities can be read back in and is equal to the original"() { + given: + "a CsvFileSink that persists the grid to a temporary directory" + def csvFileSink = new CsvFileSink(testBaseFolderPath) + + and: + "a sample grid that contains EM entities" + def originalGrid = SampleJointGrid.grid() + + when: + "the grid is persisted" + csvFileSink.persistJointGrid(originalGrid) + csvFileSink.shutdown() + + and: + "then read back in from the temporary directory" + def gridName = "sampleGrid" + def separator = "," + def readBackGrid = CsvJointGridContainerSource.read(gridName, separator, testBaseFolderPath, false) + + then: + "the original grid and the read-back grid are equal" + originalGrid == readBackGrid + } } From 14416cac6f2d6e402f14004e8e2d725bfb87fd78 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Thu, 2 Oct 2025 11:00:05 +0200 Subject: [PATCH 03/12] Add em_inputs.csv for GridIoIT --- .../datamodel/io/sink/CsvFileSinkTest.groovy | 25 ------------------- .../io/source/csv/_joint_grid/em_input.csv | 6 +++++ 2 files changed, 6 insertions(+), 25 deletions(-) create mode 100644 src/test/resources/edu/ie3/datamodel/io/source/csv/_joint_grid/em_input.csv diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index e0de935a14..0ffa7698e7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -363,29 +363,4 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { cleanup: csvFileSink.shutdown() } - - def "A persisted JointGridContainer with EmInput entities can be read back in and is equal to the original"() { - given: - "a CsvFileSink that persists the grid to a temporary directory" - def csvFileSink = new CsvFileSink(testBaseFolderPath) - - and: - "a sample grid that contains EM entities" - def originalGrid = SampleJointGrid.grid() - - when: - "the grid is persisted" - csvFileSink.persistJointGrid(originalGrid) - csvFileSink.shutdown() - - and: - "then read back in from the temporary directory" - def gridName = "sampleGrid" - def separator = "," - def readBackGrid = CsvJointGridContainerSource.read(gridName, separator, testBaseFolderPath, false) - - then: - "the original grid and the read-back grid are equal" - originalGrid == readBackGrid - } } diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_joint_grid/em_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_joint_grid/em_input.csv new file mode 100644 index 0000000000..4c960d870a --- /dev/null +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_joint_grid/em_input.csv @@ -0,0 +1,6 @@ +uuid,id,operator,operates_from,operates_until,controlStrategy,controllingEm +4e2f47a6-40f4-4952-9b2f-7b7d2558a143,em_system_1,,,,"SelfConsumptionOptimized", +a3e8e4a3-7b1b-4b1e-9e7b-8d6e3f5a2b1d,em_system_2,,,,GridSupportive,4e2f47a6-40f4-4952-9b2f-7b7d2558a143 +b8d9c5b2-6c2c-4c2d-8f8c-9e7f4a6b3c2e,em_system_3,,,,PriceReactive,4e2f47a6-40f4-4952-9b2f-7b7d2558a143 +c7f0d6c1-5d3d-4d3e-7a9d-1f8a5b7c4d3f,em__system_4,,,,StoragePriority,4e2f47a6-40f4-4952-9b2f-7b7d2558a143 +d6a1e7d0-4e4e-4e4f-6b0e-2a9b6c8d5e4a,em_system_5,,,,FeedInLimitation,4e2f47a6-40f4-4952-9b2f-7b7d2558a143 \ No newline at end of file From 5f6da26fe9402e69b60a0acd2c16716822a23e86 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:02:52 +0100 Subject: [PATCH 04/12] Add test for persisting JointGridContainer with EmInput --- .../ie3/datamodel/io/sink/CsvFileSink.java | 2 +- .../datamodel/io/source/csv/GridIoIT.groovy | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 996eceab7b..4204855b60 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -229,7 +229,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { // extract all EmInput entities Set emInputs = systemParticipants.allEntitiesAsList().stream() - .filter(Objects::nonNull) + .filter(HasEm.class::isInstance) .map(HasEm.class::cast) .map(HasEm::getControllingEm) .flatMap(Optional::stream) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy index 4b8ebf9c38..f0b948f45f 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy @@ -10,6 +10,11 @@ import edu.ie3.datamodel.io.naming.DefaultDirectoryHierarchy import edu.ie3.datamodel.io.naming.EntityPersistenceNamingStrategy import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.sink.CsvFileSink +import edu.ie3.datamodel.models.OperationTime +import edu.ie3.datamodel.models.input.EmInput +import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.container.JointGridContainer +import edu.ie3.datamodel.models.input.container.SystemParticipants import edu.ie3.util.io.FileIOUtils import spock.lang.Shared import spock.lang.Specification @@ -93,4 +98,53 @@ class GridIoIT extends Specification implements CsvTestDataMeta { then: thrown(FileException) } + + def "Input flat JointGridContainer with EmInput equals Output flat JointGridContainer."() { + given: + def gridName = "vn_simona" + def separator = "," + def baseGrid = CsvJointGridContainerSource.read(gridName, separator, jointGridFolderPath, false) + + def emInput = new EmInput( + UUID.randomUUID(), + "test_em", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + "control_strategy_test", + null + ) + + def participants = baseGrid.systemParticipants + def oldPv = participants.pvPlants.first() + def newPv = oldPv.copy().em(emInput).build() + + def newPvs = (participants.pvPlants - oldPv + newPv) + + def newParticipants = new SystemParticipants( + participants.bmPlants, + participants.chpPlants, + participants.evcs, + participants.evs, + participants.fixedFeedIns, + participants.heatPumps, + participants.loads, + newPvs, + participants.storages, + participants.wecPlants + ) + + def gridWithEm = new JointGridContainer( + baseGrid.gridName, + baseGrid.rawGrid, + newParticipants, + baseGrid.graphics + ) + + when: + sinkFlat.persistJointGrid(gridWithEm) + def readGrid = CsvJointGridContainerSource.read(gridName, separator, tempDirectory.toAbsolutePath(), false) + + then: + gridWithEm == readGrid + } } From 88b61d8b1b8bf90ee908b48148d78214da6398c1 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:29:34 +0100 Subject: [PATCH 05/12] Refactor GridIoIT setup and cleanup methods for improved clarity because test failed with duplicate key exceptions due to shared output files --- .../edu/ie3/datamodel/io/source/csv/GridIoIT.groovy | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy index f0b948f45f..77938b041e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy @@ -16,7 +16,6 @@ import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.container.JointGridContainer import edu.ie3.datamodel.models.input.container.SystemParticipants import edu.ie3.util.io.FileIOUtils -import spock.lang.Shared import spock.lang.Specification import java.nio.file.Files @@ -28,16 +27,11 @@ import java.nio.file.Path */ class GridIoIT extends Specification implements CsvTestDataMeta { - @Shared Path tempDirectory - - @Shared CsvFileSink sinkFlat - - @Shared CsvFileSink sinkHierarchic - def setupSpec() { + def setup() { FileNamingStrategy hierarchicNamingStrategy = new FileNamingStrategy( new EntityPersistenceNamingStrategy(), new DefaultDirectoryHierarchy(Path.of("output"), "vn_simona")) @@ -46,7 +40,7 @@ class GridIoIT extends Specification implements CsvTestDataMeta { sinkHierarchic = new CsvFileSink(tempDirectory.toAbsolutePath(), hierarchicNamingStrategy, ",") } - def cleanupSpec() { + def cleanup() { sinkFlat.shutdown() sinkHierarchic.shutdown() FileIOUtils.deleteRecursively(tempDirectory) From 7fa92bcb139c30a7d4b474687cffd81974a0d538 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 18 Feb 2026 11:22:04 +0100 Subject: [PATCH 06/12] reintroduce EnergyManagementUnits --- .../csv/CsvJointGridContainerSource.java | 5 + .../container/EnergyManagementUnits.java | 103 ++++++++++++++++++ .../models/input/container/GridContainer.java | 31 +++++- .../input/container/JointGridContainer.java | 9 +- .../input/container/SubGridContainer.java | 10 +- .../utils/ContainerNodeUpdateUtil.java | 4 +- .../ie3/datamodel/utils/ContainerUtils.java | 27 ++++- .../datamodel/io/source/csv/GridIoIT.groovy | 1 + .../container/JointGridContainerTest.groovy | 9 +- .../datamodel/utils/ContainerUtilsTest.groovy | 8 ++ .../ie3/test/common/ComplexTopology.groovy | 8 ++ .../common/EnergyManagementTestData.groovy | 25 +++++ .../ie3/test/common/SampleJointGrid.groovy | 2 + 13 files changed, 228 insertions(+), 14 deletions(-) create mode 100644 src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java create mode 100644 src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java index 5796454a86..bd2e6fee43 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java @@ -82,6 +82,10 @@ public static JointGridContainer read( Try.of( () -> systemParticipantSource.getSystemParticipants(operators, nodes), SourceException.class); + Try emUnits = + Try.of( + () -> new EnergyManagementUnits(new HashSet<>(emSource.getEmUnits(operators).values())), + SourceException.class); Try graphicElements = Try.of(() -> graphicSource.getGraphicElements(nodes, lines), SourceException.class); @@ -97,6 +101,7 @@ public static JointGridContainer read( gridName, rawGridElements.getOrThrow(), systemParticipants.getOrThrow(), + emUnits.getOrThrow(), graphicElements.getOrThrow()); } } diff --git a/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java b/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java new file mode 100644 index 0000000000..cabb03b010 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java @@ -0,0 +1,103 @@ +/* + * © 2023. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.container; + +import edu.ie3.datamodel.models.input.EmInput; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** Represents the accumulation of energy management units */ +public class EnergyManagementUnits implements InputContainer { + + protected final Map emUnits; + + public EnergyManagementUnits(Set emUnits) { + this.emUnits = + emUnits.stream().collect(Collectors.toMap(EmInput::getUuid, Function.identity())); + } + + /** + * Combine different already existing containers + * + * @param emUnits already existing containers + */ + public EnergyManagementUnits(Collection emUnits) { + this.emUnits = + emUnits.stream() + .flatMap(units -> units.emUnits.entrySet().stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + public Set getEmUnits() { + return new HashSet<>(emUnits.values()); + } + + @Override + public List allEntitiesAsList() { + return emUnits.values().stream().toList(); + } + + public Map getEmUnitsMap() { + return emUnits; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EnergyManagementUnits that)) return false; + return Objects.equals(emUnits, that.emUnits); + } + + @Override + public int hashCode() { + return Objects.hash(emUnits); + } + + @Override + public EnergyManagementUnitsCopyBuilder copy() { + return new EnergyManagementUnitsCopyBuilder(this); + } + + /** + * A builder pattern based approach to create copies of {@link EnergyManagementUnits} containers + * with altered field values. For detailed field descriptions refer to Javadocs of {@link + * EnergyManagementUnits} + */ + public static class EnergyManagementUnitsCopyBuilder extends InputContainerCopyBuilder { + protected Set emUnits; + + /** + * Constructor for {@link EnergyManagementUnits.EnergyManagementUnitsCopyBuilder} + * + * @param energyManagementUnits instance of {@link EnergyManagementUnits} + */ + protected EnergyManagementUnitsCopyBuilder(EnergyManagementUnits energyManagementUnits) { + this.emUnits = energyManagementUnits.getEmUnits(); + } + + /** + * Method to alter the {@link EmInput}s + * + * @param emUnits set of altered {@link EmInput}s + * @return this instance of {@link EnergyManagementUnits.EnergyManagementUnitsCopyBuilder} + */ + public EnergyManagementUnits.EnergyManagementUnitsCopyBuilder emUnits(Set emUnits) { + this.emUnits = emUnits; + return this; + } + + @Override + public EnergyManagementUnits build() { + return new EnergyManagementUnits(emUnits); + } + + @Override + public InputContainerCopyBuilder thisInstance() { + return this; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/container/GridContainer.java b/src/main/java/edu/ie3/datamodel/models/input/container/GridContainer.java index 46f50ae97c..94670cce46 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/container/GridContainer.java +++ b/src/main/java/edu/ie3/datamodel/models/input/container/GridContainer.java @@ -18,6 +18,9 @@ public abstract class GridContainer implements InputContainer /** Accumulated system participant elements */ protected final SystemParticipants systemParticipants; + /** Accumulated energy management units */ + protected final EnergyManagementUnits emUnits; + /** Accumulated graphic data entities (node graphics, line graphics) */ protected final GraphicElements graphics; @@ -25,11 +28,13 @@ protected GridContainer( String gridName, RawGridElements rawGrid, SystemParticipants systemParticipants, + EnergyManagementUnits emUnits, GraphicElements graphics) { this.gridName = gridName; this.rawGrid = rawGrid; this.systemParticipants = systemParticipants; + this.emUnits = emUnits; this.graphics = graphics; } @@ -38,6 +43,7 @@ public List allEntitiesAsList() { List allEntities = new LinkedList<>(); allEntities.addAll(rawGrid.allEntitiesAsList()); allEntities.addAll(systemParticipants.allEntitiesAsList()); + allEntities.addAll(emUnits.allEntitiesAsList()); allEntities.addAll(graphics.allEntitiesAsList()); return Collections.unmodifiableList(allEntities); } @@ -58,6 +64,10 @@ public SystemParticipants getSystemParticipants() { return systemParticipants; } + public EnergyManagementUnits getEmUnits() { + return emUnits; + } + public GraphicElements getGraphics() { return graphics; } @@ -69,12 +79,13 @@ public boolean equals(Object o) { return gridName.equals(that.gridName) && rawGrid.equals(that.rawGrid) && systemParticipants.equals(that.systemParticipants) + && emUnits.equals(that.emUnits) && graphics.equals(that.graphics); } @Override public int hashCode() { - return Objects.hash(gridName, rawGrid, systemParticipants, graphics); + return Objects.hash(gridName, rawGrid, systemParticipants, emUnits, graphics); } @Override @@ -94,6 +105,7 @@ protected abstract static class GridContainerCopyBuilder update3wTransformers( * new nodes mapping affects at least one transformer. This is necessary because by policy, the * geoPosition of a transformer is determined by its nodeA. If multiple transformers are now * chained together e.g. nodeA - trafoAtoD - nodeD - trafoDtoG - nodeG than all transformer nodes - * needs to be updated if at least one of the provided nodes is affected. Otherwise inconsistency + * needs to be updated if at least one of the provided nodes is affected. Otherwise, inconsistency * would occur because transformers would end up with multiple geoPositions which is physically * not possible. * diff --git a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java index 522dfeaa44..2ecef707e7 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java @@ -471,6 +471,7 @@ public static SubGridTopologyGraph buildSubGridTopologyGraph( String gridName, RawGridElements rawGrid, SystemParticipants systemParticipants, + EnergyManagementUnits energyManagementUnits, GraphicElements graphics) throws InvalidGridException { /* Collect the different sub nets. Through the validation of lines, it is ensured, that no galvanically connected @@ -478,11 +479,12 @@ public static SubGridTopologyGraph buildSubGridTopologyGraph( SortedSet subnetNumbers = determineSubnetNumbers(rawGrid.getNodes()); /* Build the single sub grid models */ - HashMap subgrids = - buildSubGridContainers(gridName, subnetNumbers, rawGrid, systemParticipants, graphics); + HashMap subGrids = + buildSubGridContainers( + gridName, subnetNumbers, rawGrid, systemParticipants, energyManagementUnits, graphics); /* Build the graph structure denoting the topology of the grid */ - return buildSubGridTopologyGraph(subgrids, rawGrid); + return buildSubGridTopologyGraph(subGrids, rawGrid); } /** @@ -510,6 +512,7 @@ private static HashMap buildSubGridContainers( SortedSet subnetNumbers, RawGridElements rawGrid, SystemParticipants systemParticipants, + EnergyManagementUnits energyManagementUnits, GraphicElements graphics) throws InvalidGridException { HashMap subGrids = new HashMap<>(subnetNumbers.size()); @@ -522,7 +525,12 @@ private static HashMap buildSubGridContainers( subGrids.put( subnetNumber, new SubGridContainer( - gridName, subnetNumber, rawGridElements, systemParticipantElements, graphicElements)); + gridName, + subnetNumber, + rawGridElements, + systemParticipantElements, + energyManagementUnits, + graphicElements)); } return subGrids; } @@ -693,6 +701,9 @@ public static JointGridContainer combineToJointGrid( GraphicElements graphicElements = new GraphicElements( subGridContainers.stream().map(GridContainer::getGraphics).collect(Collectors.toSet())); + EnergyManagementUnits energyManagementUnits = + new EnergyManagementUnits( + subGridContainers.stream().map(GridContainer::getEmUnits).collect(Collectors.toSet())); Map subGridMapping = subGridContainers.stream() @@ -701,7 +712,12 @@ public static JointGridContainer combineToJointGrid( SubGridTopologyGraph subGridTopologyGraph = buildSubGridTopologyGraph(subGridMapping, rawGrid); return new JointGridContainer( - gridName, rawGrid, systemParticipants, graphicElements, subGridTopologyGraph); + gridName, + rawGrid, + systemParticipants, + energyManagementUnits, + graphicElements, + subGridTopologyGraph); } /** @@ -874,6 +890,7 @@ public static SubGridContainer withTrafoNodeAsSlack(final SubGridContainer subGr subGridContainer.getRawGrid().getSwitches(), subGridContainer.getRawGrid().getMeasurementUnits()), subGridContainer.getSystemParticipants(), + subGridContainer.getEmUnits(), new GraphicElements(newNodeGraphics, subGridContainer.getGraphics().getLineGraphics())); } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy index 77938b041e..ce0249a71b 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy @@ -16,6 +16,7 @@ import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.container.JointGridContainer import edu.ie3.datamodel.models.input.container.SystemParticipants import edu.ie3.util.io.FileIOUtils +import spock.lang.Shared import spock.lang.Specification import java.nio.file.Files diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy index 5b8147f20a..21bc879578 100644 --- a/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy @@ -5,8 +5,10 @@ */ package edu.ie3.datamodel.models.input.container +import static edu.ie3.test.common.EnergyManagementTestData.emptyEnergyManagementUnits import static edu.ie3.test.common.SystemParticipantTestData.emptySystemParticipants +import edu.ie3.test.common.EnergyManagementTestData import edu.ie3.test.common.GridTestData import edu.ie3.test.common.SystemParticipantTestData import spock.lang.Specification @@ -29,7 +31,7 @@ class JointGridContainerTest extends Specification { def "A single subgrid can be used to build a JointGridContainer"() { when: - def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, emptySystemParticipants, GRAPHIC_ELEMENTS) + def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, emptySystemParticipants, emptyEnergyManagementUnits, GRAPHIC_ELEMENTS) then: noExceptionThrown() @@ -38,9 +40,10 @@ class JointGridContainerTest extends Specification { def "A JointGridContainer's copy method should work as expected"() { given: - def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, emptySystemParticipants, GRAPHIC_ELEMENTS) + def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, emptySystemParticipants, emptyEnergyManagementUnits, GRAPHIC_ELEMENTS) def rawGrid = new RawGridElements(List.of(GridTestData.lineAtoB, GridTestData.transformerAtoBtoC)) def systemParticipants = new SystemParticipants(List.of(SystemParticipantTestData.bmInput)) + def emUnits = new EnergyManagementUnits(Set.of(EnergyManagementTestData.emInput)) def graphics = new GraphicElements(Set.of(GridTestData.nodeGraphicD), Set.of(GridTestData.lineGraphicCtoD)) when: @@ -48,6 +51,7 @@ class JointGridContainerTest extends Specification { .gridName("new grid name") .rawGrid(rawGrid) .systemParticipants(systemParticipants) + .emUnits(emUnits) .graphics(graphics) .build() @@ -55,6 +59,7 @@ class JointGridContainerTest extends Specification { modifiedJointGridContainer.gridName == "new grid name" modifiedJointGridContainer.rawGrid == rawGrid modifiedJointGridContainer.systemParticipants == systemParticipants + modifiedJointGridContainer.emUnits == emUnits modifiedJointGridContainer.graphics == graphics } } diff --git a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy index b925190b91..7892cacf75 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy @@ -294,6 +294,7 @@ class ContainerUtilsTest extends Specification { Set subNetNumbers = ContainerUtils.determineSubnetNumbers(ComplexTopology.grid.rawGrid.nodes) RawGridElements rawGrid = ComplexTopology.grid.rawGrid SystemParticipants systemParticipants = ComplexTopology.grid.systemParticipants + EnergyManagementUnits energyManagementUnits = ComplexTopology.grid.emUnits GraphicElements graphics = ComplexTopology.grid.graphics HashMap expectedSubGrids = ComplexTopology.expectedSubGrids @@ -304,6 +305,7 @@ class ContainerUtilsTest extends Specification { subNetNumbers, rawGrid, systemParticipants, + energyManagementUnits, graphics) then: @@ -323,6 +325,7 @@ class ContainerUtilsTest extends Specification { Set subNetNumbers = ContainerUtils.determineSubnetNumbers(ComplexTopology.grid.rawGrid.nodes) RawGridElements rawGridInput= ComplexTopology.grid.rawGrid SystemParticipants systemParticipantsInput = ComplexTopology.grid.systemParticipants + EnergyManagementUnits energyManagementUnits = ComplexTopology.grid.emUnits GraphicElements graphicsInput = ComplexTopology.grid.graphics HashMap unmodifiedSubGrids = ComplexTopology.expectedSubGrids @@ -332,6 +335,7 @@ class ContainerUtilsTest extends Specification { subNetNumbers, rawGridInput, systemParticipantsInput, + energyManagementUnits, graphicsInput) when: @@ -386,12 +390,14 @@ class ContainerUtilsTest extends Specification { Set subNetNumbers = ContainerUtils.determineSubnetNumbers(ComplexTopology.grid.rawGrid.nodes) RawGridElements rawGrid = ComplexTopology.grid.rawGrid SystemParticipants systemParticipants = ComplexTopology.grid.systemParticipants + EnergyManagementUnits energyManagementUnits = ComplexTopology.grid.emUnits GraphicElements graphics = ComplexTopology.grid.graphics Map subgrids = ContainerUtils.buildSubGridContainers( gridName, subNetNumbers, rawGrid, systemParticipants, + energyManagementUnits, graphics) SubGridTopologyGraph expectedSubGridTopology = ComplexTopology.expectedSubGridTopology @@ -409,6 +415,7 @@ class ContainerUtilsTest extends Specification { String gridName = ComplexTopology.gridName RawGridElements rawGrid = ComplexTopology.grid.rawGrid SystemParticipants systemParticpants = ComplexTopology.grid.systemParticipants + EnergyManagementUnits energyManagementUnits = ComplexTopology.grid.emUnits GraphicElements graphics = ComplexTopology.grid.graphics SubGridTopologyGraph expectedSubGridTopology = ComplexTopology.expectedSubGridTopology @@ -417,6 +424,7 @@ class ContainerUtilsTest extends Specification { gridName, rawGrid, systemParticpants, + energyManagementUnits, graphics) then: diff --git a/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy b/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy index 1c56b3838d..172675589c 100644 --- a/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy +++ b/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy @@ -5,6 +5,7 @@ */ package edu.ie3.test.common +import static edu.ie3.test.common.EnergyManagementTestData.emptyEnergyManagementUnits import static edu.ie3.test.common.SystemParticipantTestData.emptySystemParticipants import edu.ie3.datamodel.graph.SubGridGate @@ -45,6 +46,7 @@ class ComplexTopology extends GridTestData { gridName, rawGrid, emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set)) @@ -65,6 +67,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) @@ -81,6 +84,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) @@ -97,6 +101,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) @@ -113,6 +118,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) @@ -132,6 +138,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) @@ -151,6 +158,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set), emptySystemParticipants, + emptyEnergyManagementUnits, new GraphicElements( [] as Set, [] as Set) diff --git a/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy b/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy new file mode 100644 index 0000000000..2b5ece181d --- /dev/null +++ b/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy @@ -0,0 +1,25 @@ +/* + * © 2023. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.test.common + +import edu.ie3.datamodel.models.input.EmInput +import edu.ie3.datamodel.models.input.container.EnergyManagementUnits + +class EnergyManagementTestData { + public static final String emControlStrategy = "self_optimization" + + public static final emInput = new EmInput( + UUID.fromString("977157f4-25e5-4c72-bf34-440edc778792"), + "test_emInput", + SystemParticipantTestData.operator, + SystemParticipantTestData.operationTime, + emControlStrategy, + null , + ) + + public static EnergyManagementUnits emptyEnergyManagementUnits = + new EnergyManagementUnits([] as List) +} diff --git a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy index 72d361832c..4886c8a17f 100644 --- a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy +++ b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy @@ -15,6 +15,7 @@ import edu.ie3.datamodel.models.input.connector.LineInput import edu.ie3.datamodel.models.input.connector.Transformer2WInput import edu.ie3.datamodel.models.input.connector.type.LineTypeInput import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput +import edu.ie3.datamodel.models.input.container.EnergyManagementUnits import edu.ie3.datamodel.models.input.container.GraphicElements import edu.ie3.datamodel.models.input.container.JointGridContainer import edu.ie3.datamodel.models.input.container.RawGridElements @@ -47,6 +48,7 @@ class SampleJointGrid extends SystemParticipantTestData { "sampleGrid", rawGridElements, systemParticipants(rawGridElements), + new EnergyManagementUnits(Collections.emptySet()), new GraphicElements(Collections.emptySet())) } From 226345cc018bf1c73cf81f26ef9ebcbed1e9b5d1 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Mon, 23 Mar 2026 23:42:45 +0100 Subject: [PATCH 07/12] Fix EmInput serialization in CsvFileSink.java. --- .../ie3/datamodel/io/sink/CsvFileSink.java | 7 ++- .../datamodel/io/source/csv/GridIoIT.groovy | 49 ------------------- 2 files changed, 6 insertions(+), 50 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 6ba9ed76eb..47003a76db 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -242,6 +242,11 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { em, Objects::nonNull, current -> current.getControllingEm().orElse(null))) .collect(Collectors.toSet()); + Set containerEmInputs = new HashSet<>(jointGridContainer.getEmUnits().getEmUnits()); + + Set allEmInputs = new HashSet<>(containerEmInputs); + allEmInputs.addAll(emInputs); + // persist all entities Stream.of( rawGridElements.allEntitiesAsList(), @@ -249,7 +254,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { graphicElements.allEntitiesAsList(), types, operators, - emInputs) + allEmInputs) .flatMap(Collection::stream) .collect(Collectors.toSet()) .forEach(this::persistIgnoreNested); diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy index ce0249a71b..14679f46aa 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy @@ -93,53 +93,4 @@ class GridIoIT extends Specification implements CsvTestDataMeta { then: thrown(FileException) } - - def "Input flat JointGridContainer with EmInput equals Output flat JointGridContainer."() { - given: - def gridName = "vn_simona" - def separator = "," - def baseGrid = CsvJointGridContainerSource.read(gridName, separator, jointGridFolderPath, false) - - def emInput = new EmInput( - UUID.randomUUID(), - "test_em", - OperatorInput.NO_OPERATOR_ASSIGNED, - OperationTime.notLimited(), - "control_strategy_test", - null - ) - - def participants = baseGrid.systemParticipants - def oldPv = participants.pvPlants.first() - def newPv = oldPv.copy().em(emInput).build() - - def newPvs = (participants.pvPlants - oldPv + newPv) - - def newParticipants = new SystemParticipants( - participants.bmPlants, - participants.chpPlants, - participants.evcs, - participants.evs, - participants.fixedFeedIns, - participants.heatPumps, - participants.loads, - newPvs, - participants.storages, - participants.wecPlants - ) - - def gridWithEm = new JointGridContainer( - baseGrid.gridName, - baseGrid.rawGrid, - newParticipants, - baseGrid.graphics - ) - - when: - sinkFlat.persistJointGrid(gridWithEm) - def readGrid = CsvJointGridContainerSource.read(gridName, separator, tempDirectory.toAbsolutePath(), false) - - then: - gridWithEm == readGrid - } } From 0d6ea6efd1e5e9cca4901d5feb4cdeda6a2c7400 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:59:48 +0100 Subject: [PATCH 08/12] add missing EmInput to SampleJointGrid data and fmt --- .../ie3/datamodel/io/sink/CsvFileSink.java | 20 ++----------------- .../datamodel/io/sink/CsvFileSinkTest.groovy | 1 - .../ie3/test/common/SampleJointGrid.groovy | 2 +- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 47003a76db..92bbd5938c 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -10,7 +10,6 @@ import edu.ie3.datamodel.io.csv.BufferedCsvWriter; import edu.ie3.datamodel.io.csv.CsvFileDefinition; import edu.ie3.datamodel.io.extractor.Extractor; -import edu.ie3.datamodel.io.extractor.HasEm; import edu.ie3.datamodel.io.extractor.NestedEntity; import edu.ie3.datamodel.io.naming.FileNamingStrategy; import edu.ie3.datamodel.io.processor.ProcessorProvider; @@ -230,22 +229,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { .collect(Collectors.toSet()); // extract all EmInput entities - Set emInputs = - systemParticipants.allEntitiesAsList().stream() - .filter(HasEm.class::isInstance) - .map(HasEm.class::cast) - .map(HasEm::getControllingEm) - .flatMap(Optional::stream) - .flatMap( - em -> - Stream.iterate( - em, Objects::nonNull, current -> current.getControllingEm().orElse(null))) - .collect(Collectors.toSet()); - - Set containerEmInputs = new HashSet<>(jointGridContainer.getEmUnits().getEmUnits()); - - Set allEmInputs = new HashSet<>(containerEmInputs); - allEmInputs.addAll(emInputs); + Set emInputs = new HashSet<>(jointGridContainer.getEmUnits().getEmUnits()); // persist all entities Stream.of( @@ -254,7 +238,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { graphicElements.allEntitiesAsList(), types, operators, - allEmInputs) + emInputs) .flatMap(Collection::stream) .collect(Collectors.toSet()) .forEach(this::persistIgnoreNested); diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index c6a1d0c853..f3e129e4e2 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -15,7 +15,6 @@ import edu.ie3.datamodel.io.processor.input.InputEntityProcessor import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessor import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessorKey -import edu.ie3.datamodel.io.source.csv.CsvJointGridContainerSource import edu.ie3.datamodel.models.OperationTime import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.EmInput diff --git a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy index eacba3bd03..6b9beaee5e 100644 --- a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy +++ b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy @@ -48,7 +48,7 @@ class SampleJointGrid extends SystemParticipantTestData { "sampleGrid", rawGridElements, systemParticipants(rawGridElements), - new EnergyManagementUnits(Collections.emptySet()), + new EnergyManagementUnits(Collections.singleton(emInput)), new GraphicElements(Collections.emptySet())) } From c1c79edc28313f7584cf780809f3902995209fa7 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:24:33 +0100 Subject: [PATCH 09/12] Refactor persistJointGrid to remove redundant set allocations --- .../ie3/datamodel/io/sink/CsvFileSink.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 92bbd5938c..88b5a4703e 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -187,7 +187,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { GraphicElements graphicElements = jointGridContainer.getGraphics(); // extract types - Set types = + Stream types = Stream.of( lines, transformer2Ws, @@ -200,11 +200,10 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { storages, wecPlants) .flatMap(Collection::stream) - .map(Extractor::extractType) - .collect(Collectors.toSet()); + .map(Extractor::extractType); // extract operators - Set operators = + Stream operators = Stream.of( nodes, lines, @@ -225,21 +224,17 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { wecPlants) .flatMap(Collection::stream) .map(Extractor::extractOperator) - .flatMap(Optional::stream) - .collect(Collectors.toSet()); - - // extract all EmInput entities - Set emInputs = new HashSet<>(jointGridContainer.getEmUnits().getEmUnits()); + .flatMap(Optional::stream); // persist all entities Stream.of( - rawGridElements.allEntitiesAsList(), - systemParticipants.allEntitiesAsList(), - graphicElements.allEntitiesAsList(), + rawGridElements.allEntitiesAsList().stream(), + systemParticipants.allEntitiesAsList().stream(), + graphicElements.allEntitiesAsList().stream(), + jointGridContainer.getEmUnits().getEmUnits().stream(), types, - operators, - emInputs) - .flatMap(Collection::stream) + operators) + .flatMap(s -> s) .collect(Collectors.toSet()) .forEach(this::persistIgnoreNested); } From acc2321166a2e7dfc5e10de376e11487f3680abd Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 25 Mar 2026 17:57:24 +0100 Subject: [PATCH 10/12] add examples for emControlStrategy to docs --- docs/readthedocs/models/input/em.md | 2 +- .../groovy/edu/ie3/test/common/EnergyManagementTestData.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/readthedocs/models/input/em.md b/docs/readthedocs/models/input/em.md index 02e168d0d4..787170578d 100644 --- a/docs/readthedocs/models/input/em.md +++ b/docs/readthedocs/models/input/em.md @@ -35,7 +35,7 @@ Participants are connected to an EM each via their `em` field. * - controlStrategy - - - String representation (e.g. name) of a control strategy + - String representation (e.g. name) of a control strategy. E.g.: PRIORITIZED or PROPORTIONAL * - controllingEm - diff --git a/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy b/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy index 2b5ece181d..832387557a 100644 --- a/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/EnergyManagementTestData.groovy @@ -9,7 +9,7 @@ import edu.ie3.datamodel.models.input.EmInput import edu.ie3.datamodel.models.input.container.EnergyManagementUnits class EnergyManagementTestData { - public static final String emControlStrategy = "self_optimization" + public static final String emControlStrategy = "PRIORITIZED" public static final emInput = new EmInput( UUID.fromString("977157f4-25e5-4c72-bf34-440edc778792"), From 57a90c4d2bfeba764f22327c01aac5c5e5cab752 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 25 Mar 2026 18:05:05 +0100 Subject: [PATCH 11/12] optimize imports --- .../ie3/datamodel/io/sink/CsvFileSinkTest.groovy | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index f3e129e4e2..6021ebd078 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -34,23 +34,14 @@ import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput -import edu.ie3.datamodel.models.result.system.EmResult -import edu.ie3.datamodel.models.result.system.EvResult -import edu.ie3.datamodel.models.result.system.EvcsResult -import edu.ie3.datamodel.models.result.system.FlexOptionsResult -import edu.ie3.datamodel.models.result.system.PvResult -import edu.ie3.datamodel.models.result.system.WecResult +import edu.ie3.datamodel.models.result.system.* import edu.ie3.datamodel.models.timeseries.TimeSeries import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue import edu.ie3.datamodel.models.value.EnergyPriceValue import edu.ie3.datamodel.models.value.Value -import edu.ie3.test.common.GridTestData -import edu.ie3.test.common.SampleJointGrid -import edu.ie3.test.common.SystemParticipantTestData -import edu.ie3.test.common.ThermalUnitInputTestData -import edu.ie3.test.common.TimeSeriesTestData +import edu.ie3.test.common.* import edu.ie3.util.TimeUtil import edu.ie3.util.io.FileIOUtils import spock.lang.Shared From cad3c6b86ed0e871a2d010139e407b0ca4566cc0 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:12:18 +0100 Subject: [PATCH 12/12] Adres review comments --- .../ie3/datamodel/io/sink/CsvFileSink.java | 21 ++++++++++--------- .../container/EnergyManagementUnits.java | 2 +- .../datamodel/io/source/csv/GridIoIT.groovy | 6 ------ 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java index 88b5a4703e..14d3f4898e 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/CsvFileSink.java @@ -187,7 +187,7 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { GraphicElements graphicElements = jointGridContainer.getGraphics(); // extract types - Stream types = + Set types = Stream.of( lines, transformer2Ws, @@ -200,10 +200,11 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { storages, wecPlants) .flatMap(Collection::stream) - .map(Extractor::extractType); + .map(Extractor::extractType) + .collect(Collectors.toSet()); // extract operators - Stream operators = + Set operators = Stream.of( nodes, lines, @@ -224,18 +225,18 @@ public void persistJointGrid(JointGridContainer jointGridContainer) { wecPlants) .flatMap(Collection::stream) .map(Extractor::extractOperator) - .flatMap(Optional::stream); + .flatMap(Optional::stream) + .collect(Collectors.toSet()); // persist all entities Stream.of( - rawGridElements.allEntitiesAsList().stream(), - systemParticipants.allEntitiesAsList().stream(), - graphicElements.allEntitiesAsList().stream(), - jointGridContainer.getEmUnits().getEmUnits().stream(), + rawGridElements.allEntitiesAsList(), + systemParticipants.allEntitiesAsList(), + graphicElements.allEntitiesAsList(), + jointGridContainer.getEmUnits().getEmUnits().stream().toList(), types, operators) - .flatMap(s -> s) - .collect(Collectors.toSet()) + .flatMap(Collection::stream) .forEach(this::persistIgnoreNested); } diff --git a/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java b/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java index cabb03b010..1b9a0454aa 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java +++ b/src/main/java/edu/ie3/datamodel/models/input/container/EnergyManagementUnits.java @@ -13,7 +13,7 @@ /** Represents the accumulation of energy management units */ public class EnergyManagementUnits implements InputContainer { - protected final Map emUnits; + private final Map emUnits; public EnergyManagementUnits(Set emUnits) { this.emUnits = diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy index 14679f46aa..2c33c5797c 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/GridIoIT.groovy @@ -10,13 +10,7 @@ import edu.ie3.datamodel.io.naming.DefaultDirectoryHierarchy import edu.ie3.datamodel.io.naming.EntityPersistenceNamingStrategy import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.sink.CsvFileSink -import edu.ie3.datamodel.models.OperationTime -import edu.ie3.datamodel.models.input.EmInput -import edu.ie3.datamodel.models.input.OperatorInput -import edu.ie3.datamodel.models.input.container.JointGridContainer -import edu.ie3.datamodel.models.input.container.SystemParticipants import edu.ie3.util.io.FileIOUtils -import spock.lang.Shared import spock.lang.Specification import java.nio.file.Files