From 5b47c6b6f6847093c66600c9e611bf7b2bc08954 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 9 Jan 2026 14:15:28 +0100 Subject: [PATCH 1/3] Refactored the handling of power profiles --- CHANGELOG.md | 1 + .../input/participant/LoadInputFactory.java | 19 +- .../timeseries/BdewLoadProfileFactory.java | 57 ++--- .../timeseries/LoadProfileFactory.java | 16 +- .../timeseries/RandomLoadProfileFactory.java | 24 +- .../io/naming/DatabaseNamingStrategy.java | 2 +- .../EntityPersistenceNamingStrategy.java | 4 +- .../FileLoadProfileMetaInformation.java | 7 + .../LoadProfileMetaInformation.java | 22 +- .../ie3/datamodel/io/processor/Processor.java | 3 + .../timeseries/TimeSeriesProcessor.java | 3 +- .../timeseries/TimeSeriesProcessorKey.java | 2 +- .../edu/ie3/datamodel/io/sink/SqlSink.java | 4 +- .../io/source/LoadProfileSource.java | 40 ++-- .../datamodel/io/source/PowerValueSource.java | 22 +- .../TimeSeriesMetaInformationSource.java | 5 +- .../io/source/csv/CsvDataSource.java | 11 +- .../io/source/csv/CsvLoadProfileSource.java | 20 +- .../io/source/file/FileDataSource.java | 5 +- .../FileTimeSeriesMetaInformationSource.java | 3 +- .../io/source/sql/SqlLoadProfileSource.java | 23 +- .../SqlTimeSeriesMetaInformationSource.java | 3 +- .../models/input/system/LoadInput.java | 55 +++-- .../profile/BdewStandardLoadProfile.java | 19 +- .../datamodel/models/profile/LoadProfile.java | 66 +----- .../NbwTemperatureDependantLoadProfile.java | 19 +- .../models/profile/PowerProfile.java | 2 +- .../models/profile/PowerProfileKey.java | 68 ++++++ .../models/profile/StandardLoadProfile.java | 14 +- .../TemperatureDependantLoadProfile.java | 15 +- .../repetitive/BdewLoadProfileTimeSeries.java | 13 +- .../repetitive/LoadProfileTimeSeries.java | 28 +-- .../RandomLoadProfileTimeSeries.java | 9 +- .../models/value/load/BdewLoadValues.java | 23 +- .../models/value/load/LoadValues.java | 6 +- .../models/value/load/RandomLoadValues.java | 6 +- .../SystemParticipantValidationUtils.java | 55 ++--- .../participant/LoadInputFactoryTest.groovy | 4 +- .../BdewLoadProfileFactoryTest.groovy | 8 +- .../RandomLoadProfileFactoryTest.groovy | 8 +- ...EntityPersistenceNamingStrategyTest.groovy | 6 +- .../io/naming/FileNamingStrategyTest.groovy | 16 +- .../input/InputEntityProcessorTest.groovy | 2 +- .../io/source/LoadProfileSourceTest.groovy | 31 ++- .../io/source/csv/CsvDataSourceTest.groovy | 9 +- .../source/sql/SqlLoadProfileSourceIT.groovy | 2 +- .../models/input/system/LoadInputTest.groovy | 4 +- .../models/profile/LoadProfileTest.groovy | 222 ------------------ .../models/profile/PowerProfileKeyTest.groovy | 124 ++++++++++ ...ystemParticipantValidationUtilsTest.groovy | 35 +-- .../resources/load/BdewLoadProfileTest.groovy | 2 +- .../ie3/test/common/SampleJointGrid.groovy | 4 +- .../common/SystemParticipantTestData.groovy | 5 +- .../ie3/test/common/TimeSeriesTestData.groovy | 2 +- 54 files changed, 490 insertions(+), 688 deletions(-) create mode 100644 src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java delete mode 100644 src/test/groovy/edu/ie3/datamodel/models/profile/LoadProfileTest.groovy create mode 100644 src/test/groovy/edu/ie3/datamodel/models/profile/PowerProfileKeyTest.groovy diff --git a/CHANGELOG.md b/CHANGELOG.md index b5f85f8719..592ba103d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactor CSV handling into shared file-based infrastructure. [#1450](https://github.com/ie3-institute/PowerSystemDataModel/issues/1445) - Change `testcontainers` to v2 [#1496](https://github.com/ie3-institute/PowerSystemDataModel/issues/1496) - Update thermal input documentation [#1506](https://github.com/ie3-institute/PowerSystemDataModel/issues/1506) +- Refactored the handling of power profiles [#1514](https://github.com/ie3-institute/PowerSystemDataModel/issues/1514) ## [8.1.0] - 2025-07-25 diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java index 71af7c515a..7504ec9ab8 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java @@ -5,7 +5,6 @@ */ package edu.ie3.datamodel.io.factory.input.participant; -import edu.ie3.datamodel.exceptions.ParsingException; import edu.ie3.datamodel.models.OperationTime; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.input.EmInput; @@ -13,18 +12,14 @@ import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.models.input.system.LoadInput; import edu.ie3.datamodel.models.input.system.characteristic.ReactivePowerCharacteristic; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import java.util.UUID; import javax.measure.quantity.Energy; import javax.measure.quantity.Power; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import tech.units.indriya.ComparableQuantity; public class LoadInputFactory extends SystemParticipantInputEntityFactory { - private static final Logger logger = LoggerFactory.getLogger(LoadInputFactory.class); - private static final String LOAD_PROFILE = "loadProfile"; private static final String E_CONS_ANNUAL = "eConsAnnual"; private static final String S_RATED = "sRated"; @@ -48,16 +43,8 @@ protected LoadInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - LoadProfile loadProfile; - try { - loadProfile = LoadProfile.parse(data.getField(LOAD_PROFILE)); - } catch (ParsingException e) { - logger.warn( - "Cannot parse the standard load profile \"{}\" of load \"{}\". Assign no load profile instead.", - data.getField(LOAD_PROFILE), - id); - loadProfile = LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE; - } + PowerProfileKey loadProfile = new PowerProfileKey(data.getField(LOAD_PROFILE)); + final EmInput em = data.getControllingEm().orElse(null); final ComparableQuantity eConsAnnual = diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java index 67451014ee..1c730489a8 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java @@ -5,11 +5,10 @@ */ package edu.ie3.datamodel.io.factory.timeseries; +import static edu.ie3.datamodel.models.profile.BdewStandardLoadProfile.*; import static tech.units.indriya.unit.Units.WATT; -import edu.ie3.datamodel.exceptions.FactoryException; -import edu.ie3.datamodel.exceptions.ParsingException; -import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry; import edu.ie3.datamodel.models.timeseries.repetitive.BdewLoadProfileTimeSeries; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; @@ -27,8 +26,7 @@ import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; -public class BdewLoadProfileFactory - extends LoadProfileFactory { +public class BdewLoadProfileFactory extends LoadProfileFactory { // 1999 profile scheme public static final BdewLoadValues.BdewMap BDEW1999_FIELDS = BdewKey.toMap(BdewScheme.BDEW1999); @@ -69,33 +67,25 @@ protected List> getFields(Class entityClass) { @Override public BdewLoadProfileTimeSeries build( - BdewStandardLoadProfile profile, Set> entries) { - ComparableQuantity maxPower = calculateMaxPower(profile, entries); - ComparableQuantity profileEnergyScaling = getLoadProfileEnergyScaling(profile); + PowerProfileKey powerProfileKey, Set> entries) { + ComparableQuantity maxPower = calculateMaxPower(powerProfileKey, entries); + ComparableQuantity profileEnergyScaling = getLoadProfileEnergyScaling(powerProfileKey); - return new BdewLoadProfileTimeSeries(profile, entries, maxPower, profileEnergyScaling); - } - - @Override - public BdewStandardLoadProfile parseProfile(String profile) { - try { - return BdewStandardLoadProfile.get(profile); - } catch (ParsingException e) { - throw new FactoryException("An error occurred while parsing the profile: " + profile, e); - } + return new BdewLoadProfileTimeSeries(powerProfileKey, entries, maxPower, profileEnergyScaling); } @Override public ComparableQuantity calculateMaxPower( - BdewStandardLoadProfile loadProfile, Set> entries) { - Function valueExtractor = - switch (loadProfile) { - case H0, H25, P25, S25 -> - // maximum dynamization factor is on day 366 (leap year) or day 365 (regular year). - // The difference between day 365 and day 366 is negligible, thus pick 366 - v -> BdewLoadValues.dynamization(v.getMaxValue(true), 366); - default -> v -> v.getMaxValue(false); - }; + PowerProfileKey powerProfileKey, Set> entries) { + Function valueExtractor; + + if (powerProfileKey.equalsAny(H25, G25, P25, S25)) { + // maximum dynamization factor is on day 366 (leap year) or day 365 (regular year). + // The difference between day 365 and day 366 is negligible, thus pick 366 + valueExtractor = v -> BdewLoadValues.dynamization(v.getMaxValue(true), 366); + } else { + valueExtractor = v -> v.getMaxValue(false); + } double maxPower = entries.stream() @@ -109,14 +99,13 @@ public ComparableQuantity calculateMaxPower( /** Returns the load profile energy scaling. The default value is 1000 kWh */ @Override - public ComparableQuantity getLoadProfileEnergyScaling( - BdewStandardLoadProfile loadProfile) { - + public ComparableQuantity getLoadProfileEnergyScaling(PowerProfileKey powerProfileKey) { // the updated profiled are scaled to 1 million kWh -> 1000 MWh // old profiles are scaled to 1000 kWh - return switch (loadProfile) { - case H25, G25, L25, P25, S25 -> Quantities.getQuantity(1000d, PowerSystemUnits.MEGAWATTHOUR); - default -> Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR); - }; + if (powerProfileKey.equalsAny(H25, G25, L25, P25, S25)) { + return Quantities.getQuantity(1000d, PowerSystemUnits.MEGAWATTHOUR); + } else { + return Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR); + } } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java index bb0f4cd6e2..3fe8048337 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java @@ -6,7 +6,7 @@ package edu.ie3.datamodel.io.factory.timeseries; import edu.ie3.datamodel.io.factory.Factory; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries; import edu.ie3.datamodel.models.value.load.LoadValues; @@ -20,10 +20,9 @@ /** * Base factory for all {@link LoadProfileTimeSeries}. * - * @param

type of load profile * @param type of load values */ -public abstract class LoadProfileFactory

> +public abstract class LoadProfileFactory extends Factory, LoadProfileEntry> { protected static final String QUARTER_HOUR = "quarterHour"; @@ -36,20 +35,19 @@ protected LoadProfileFactory(Class... valueClass) { super(valueClass); } - public abstract LoadProfileTimeSeries build(P profile, Set> entries); - - public abstract P parseProfile(String profile); + public abstract LoadProfileTimeSeries build( + PowerProfileKey powerProfileKey, Set> entries); /** * Calculates the maximum average power consumption per quarter-hour for a given calculated over * all seasons and weekday types of given load profile * - * @param loadProfile given load profile + * @param powerProfileKey given load profile key * @param entries with power values * @return the maximal average power */ public abstract ComparableQuantity calculateMaxPower( - P loadProfile, Set> entries); + PowerProfileKey powerProfileKey, Set> entries); /** Returns the quarter-hour field. */ public String getTimeFieldString() { @@ -57,7 +55,7 @@ public String getTimeFieldString() { } /** Returns the load profile energy scaling. The default value is 1000 kWh */ - public ComparableQuantity getLoadProfileEnergyScaling(P loadProfile) { + public ComparableQuantity getLoadProfileEnergyScaling(PowerProfileKey powerProfileKey) { return Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java index 2addfa46ad..1dfbcc815d 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java @@ -5,10 +5,9 @@ */ package edu.ie3.datamodel.io.factory.timeseries; -import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE; import static tech.units.indriya.unit.Units.WATT; -import edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries; import edu.ie3.datamodel.models.value.load.RandomLoadValues; @@ -20,8 +19,7 @@ import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; -public class RandomLoadProfileFactory - extends LoadProfileFactory { +public class RandomLoadProfileFactory extends LoadProfileFactory { public static final String K_WEEKDAY = "kWd"; public static final String K_SATURDAY = "kSa"; public static final String K_SUNDAY = "kSu"; @@ -72,16 +70,12 @@ protected List> getFields(Class entityClass) { @Override public RandomLoadProfileTimeSeries build( - RandomLoadProfile profile, Set> entries) { - ComparableQuantity maxPower = calculateMaxPower(profile, entries); - ComparableQuantity profileEnergyScaling = getLoadProfileEnergyScaling(profile); + PowerProfileKey powerProfileKey, Set> entries) { + ComparableQuantity maxPower = calculateMaxPower(powerProfileKey, entries); + ComparableQuantity profileEnergyScaling = getLoadProfileEnergyScaling(powerProfileKey); - return new RandomLoadProfileTimeSeries(profile, entries, maxPower, profileEnergyScaling); - } - - @Override - public RandomLoadProfile parseProfile(String profile) { - return RANDOM_LOAD_PROFILE; + return new RandomLoadProfileTimeSeries( + powerProfileKey, entries, maxPower, profileEnergyScaling); } /** @@ -92,7 +86,7 @@ public RandomLoadProfile parseProfile(String profile) { */ @Override public ComparableQuantity calculateMaxPower( - RandomLoadProfile loadProfile, Set> loadProfileEntries) { + PowerProfileKey powerProfileKey, Set> loadProfileEntries) { return Quantities.getQuantity(159d, WATT); } @@ -107,7 +101,7 @@ public ComparableQuantity calculateMaxPower( * 2019. */ @Override - public ComparableQuantity getLoadProfileEnergyScaling(RandomLoadProfile loadProfile) { + public ComparableQuantity getLoadProfileEnergyScaling(PowerProfileKey powerProfileKey) { return Quantities.getQuantity(716.5416966513656, PowerSystemUnits.KILOWATTHOUR); } } diff --git a/src/main/java/edu/ie3/datamodel/io/naming/DatabaseNamingStrategy.java b/src/main/java/edu/ie3/datamodel/io/naming/DatabaseNamingStrategy.java index 3d4f63ff6b..7e720e2d28 100644 --- a/src/main/java/edu/ie3/datamodel/io/naming/DatabaseNamingStrategy.java +++ b/src/main/java/edu/ie3/datamodel/io/naming/DatabaseNamingStrategy.java @@ -97,7 +97,7 @@ Optional getEntityName(T timeSeries) { logger.error("Unable to determine content of time series {}", timeSeries); return Optional.empty(); } - } else if (timeSeries instanceof LoadProfileTimeSeries) { + } else if (timeSeries instanceof LoadProfileTimeSeries) { return Optional.of(getLoadProfileEntityName()); } else { logger.error("There is no naming strategy defined for {}", timeSeries); diff --git a/src/main/java/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategy.java b/src/main/java/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategy.java index 12a42e922a..d3bc1a21b8 100644 --- a/src/main/java/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategy.java +++ b/src/main/java/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategy.java @@ -371,12 +371,12 @@ Optional getEntityName(T timeSeries) { logger.error("Unable to determine content of time series {}", timeSeries); return Optional.empty(); } - } else if (timeSeries instanceof LoadProfileTimeSeries loadProfileTimeSeries) { + } else if (timeSeries instanceof LoadProfileTimeSeries loadProfileTimeSeries) { return Optional.of( prefix .concat("lpts") .concat("_") - .concat(loadProfileTimeSeries.getLoadProfile().getKey()) + .concat(loadProfileTimeSeries.getPowerProfileKey().getValue()) .concat(suffix)); } else { logger.error("There is no naming strategy defined for {}", timeSeries); diff --git a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/FileLoadProfileMetaInformation.java b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/FileLoadProfileMetaInformation.java index 7209b818be..16e9ce35b6 100644 --- a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/FileLoadProfileMetaInformation.java +++ b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/FileLoadProfileMetaInformation.java @@ -19,6 +19,13 @@ public FileLoadProfileMetaInformation(String profile, Path fullFilePath, FileTyp this.fileType = fileType; } + public FileLoadProfileMetaInformation( + LoadProfileMetaInformation metaInformation, Path fullFilePath, FileType fileType) { + super(metaInformation.getProfileKey()); + this.fullFilePath = fullFilePath; + this.fileType = fileType; + } + public Path getFullFilePath() { return fullFilePath; } diff --git a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/LoadProfileMetaInformation.java b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/LoadProfileMetaInformation.java index 17e162618b..d25d8fadbe 100644 --- a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/LoadProfileMetaInformation.java +++ b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/LoadProfileMetaInformation.java @@ -5,20 +5,26 @@ */ package edu.ie3.datamodel.io.naming.timeseries; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import java.util.Objects; import java.util.UUID; /** Specific meta information, that can be derived from a load profile time series file */ public class LoadProfileMetaInformation extends TimeSeriesMetaInformation { - private final String profile; + private final PowerProfileKey profileKey; - public LoadProfileMetaInformation(String profile) { + public LoadProfileMetaInformation(String profileKey) { super(UUID.randomUUID()); - this.profile = profile; + this.profileKey = new PowerProfileKey(profileKey); } - public String getProfile() { - return profile; + public LoadProfileMetaInformation(PowerProfileKey powerProfileKey) { + super(UUID.randomUUID()); + this.profileKey = powerProfileKey; + } + + public PowerProfileKey getProfileKey() { + return profileKey; } @Override @@ -26,16 +32,16 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof LoadProfileMetaInformation that)) return false; if (!super.equals(o)) return false; - return profile.equals(that.profile); + return profileKey.equals(that.profileKey); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), profile); + return Objects.hash(super.hashCode(), profileKey); } @Override public String toString() { - return "LoadProfileTimeSeriesMetaInformation{profile='" + profile + '}'; + return "LoadProfileTimeSeriesMetaInformation{profileKey='" + profileKey.getValue() + '}'; } } diff --git a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java index d232dbf27b..d69c54628b 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java @@ -15,6 +15,7 @@ import edu.ie3.datamodel.models.input.connector.SwitchInput; import edu.ie3.datamodel.models.input.system.characteristic.CharacteristicInput; import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.result.CongestionResult; import edu.ie3.datamodel.models.voltagelevels.VoltageLevel; import edu.ie3.datamodel.utils.Try; @@ -304,6 +305,8 @@ protected String processMethodResult( resultStringBuilder.append(((CharacteristicInput) methodReturnObject).serialize()); case "InputModelType" -> resultStringBuilder.append(((CongestionResult.InputModelType) methodReturnObject).type); + case "PowerProfileKey" -> + resultStringBuilder.append(((PowerProfileKey) methodReturnObject).getValue()); default -> throw new EntityProcessorException( "Unable to process value for attribute/field '" diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index 430746a346..b43f9b0220 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -155,7 +155,8 @@ private SortedMap buildFieldToSource( jointMapping.put(fieldName, new FieldSourceToMethod(source, getter)); /* Get the mapping from field name to getter method ignoring the getter for returning all entries */ - mapFieldNameToGetter(timeSeriesClass, Arrays.asList("entries", "uuid", "type", "loadProfile")) + mapFieldNameToGetter( + timeSeriesClass, Arrays.asList("entries", "uuid", "type", "powerProfileKey")) .forEach(addFunction.apply(TIMESERIES)); /* Get the mapping from field name to getter method for the entry, but ignoring the getter for the value */ diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessorKey.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessorKey.java index cb918d5bef..a5e1c81dea 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessorKey.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessorKey.java @@ -42,7 +42,7 @@ public TimeSeriesProcessorKey(TimeSeries, ?, ?> tim this.valueClass = value.getClass(); - if (value instanceof LoadValues loadValues) { + if (value instanceof LoadValues loadValues) { this.scheme = loadValues.getScheme(); } else { this.scheme = Optional.empty(); diff --git a/src/main/java/edu/ie3/datamodel/io/sink/SqlSink.java b/src/main/java/edu/ie3/datamodel/io/sink/SqlSink.java index eb007b99ca..46f61facf9 100644 --- a/src/main/java/edu/ie3/datamodel/io/sink/SqlSink.java +++ b/src/main/java/edu/ie3/datamodel/io/sink/SqlSink.java @@ -251,8 +251,8 @@ private , V extends Value, R extends Value> void pe TriFunction queryBuilder; String timeSeriesIdentifier; - if (timeSeries instanceof LoadProfileTimeSeries lpts) { - timeSeriesIdentifier = lpts.getLoadProfile().getKey(); + if (timeSeries instanceof LoadProfileTimeSeries lpts) { + timeSeriesIdentifier = lpts.getPowerProfileKey().getValue(); queryBuilder = this::basicInsertQueryValuesLPTS; } else { timeSeriesIdentifier = timeSeries.getUuid().toString(); diff --git a/src/main/java/edu/ie3/datamodel/io/source/LoadProfileSource.java b/src/main/java/edu/ie3/datamodel/io/source/LoadProfileSource.java index a37913b46e..6fa9a8273f 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/LoadProfileSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/LoadProfileSource.java @@ -18,7 +18,8 @@ import edu.ie3.datamodel.io.source.csv.CsvDataSource; import edu.ie3.datamodel.io.source.csv.CsvLoadProfileSource; import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries; import edu.ie3.datamodel.models.value.Value; @@ -33,17 +34,17 @@ import java.util.function.Function; import java.util.stream.Collectors; -public abstract class LoadProfileSource

> - extends EntitySource implements PowerValueSource.TimeSeriesBased { - protected final P profile; +public abstract class LoadProfileSource extends EntitySource + implements PowerValueSource.TimeSeriesBased { + protected final PowerProfileKey powerProfileKey; protected final Class entryClass; - protected final LoadProfileFactory entryFactory; + protected final LoadProfileFactory entryFactory; protected LoadProfileSource( LoadProfileMetaInformation metaInformation, Class entryClass, - LoadProfileFactory entryFactory) { - this.profile = entryFactory.parseProfile(metaInformation.getProfile()); + LoadProfileFactory entryFactory) { + this.powerProfileKey = metaInformation.getProfileKey(); this.entryClass = entryClass; this.entryFactory = entryFactory; } @@ -65,24 +66,24 @@ protected Try, FactoryException> createEntries( public abstract Set> getEntries(); @Override - public P getProfile() { - return profile; + public PowerProfileKey getProfileKey() { + return powerProfileKey; } @Override public Optional getNextTimeKey(ZonedDateTime time) { - return Optional.of(time.plusSeconds(getResolution(getProfile()))); + return Optional.of(time.plusSeconds(getResolution(getProfileKey()))); } /** - * Returns the resolution for the given {@link LoadProfile}. + * Returns the resolution for the given {@link PowerProfile}. * - * @param loadProfile given load profile + * @param powerProfileKey given load profile key * @return the resolution in seconds. */ - public static long getResolution(LoadProfile loadProfile) { + public static long getResolution(PowerProfileKey powerProfileKey) { - if (loadProfile == LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE) { + if (powerProfileKey.noKeyAssigned) { // since no load profile was assigned, we return the maximal possible value return Long.MAX_VALUE; } else { @@ -96,9 +97,8 @@ public static long getResolution(LoadProfile loadProfile) { * * @return a map: load profile to load profile source */ - public static Map< - BdewStandardLoadProfile, CsvLoadProfileSource> - getBdewLoadProfiles() throws SourceException { + public static Map> getBdewLoadProfiles() + throws SourceException { CsvDataSource buildInSource = getBuildInSource(LoadProfileSource.class, "/load"); BdewLoadProfileFactory factory = new BdewLoadProfileFactory(); @@ -111,7 +111,7 @@ public static long getResolution(LoadProfile loadProfile) { metaInformation -> new CsvLoadProfileSource<>( buildInSource, metaInformation, BdewLoadValues.class, factory)) - .collect(Collectors.toMap(CsvLoadProfileSource::getProfile, Function.identity())); + .collect(Collectors.toMap(CsvLoadProfileSource::getProfileKey, Function.identity())); } /** @@ -119,8 +119,8 @@ public static long getResolution(LoadProfile loadProfile) { * * @return the random load profile source */ - public static CsvLoadProfileSource - getRandomLoadProfile() throws SourceException { + public static CsvLoadProfileSource getRandomLoadProfile() + throws SourceException { CsvDataSource buildInSource = getBuildInSource(LoadProfileSource.class, "/load"); FileLoadProfileMetaInformation metaInformation = diff --git a/src/main/java/edu/ie3/datamodel/io/source/PowerValueSource.java b/src/main/java/edu/ie3/datamodel/io/source/PowerValueSource.java index aca55b78a1..61a00c8acb 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/PowerValueSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/PowerValueSource.java @@ -5,8 +5,7 @@ */ package edu.ie3.datamodel.io.source; -import edu.ie3.datamodel.models.profile.LoadProfile; -import edu.ie3.datamodel.models.profile.PowerProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.PValue; import java.time.ZonedDateTime; import java.util.Optional; @@ -16,12 +15,11 @@ import tech.units.indriya.ComparableQuantity; /** Interface defining base functionality for power value sources. */ -public sealed interface PowerValueSource< - P extends PowerProfile, I extends PowerValueSource.PowerValueIdentifier> +public sealed interface PowerValueSource permits PowerValueSource.MarkovBased, PowerValueSource.TimeSeriesBased { /** Returns the profile of this source. */ - P getProfile(); + PowerProfileKey getProfileKey(); /** * Method to get a supplier for the next power value based on the provided input data. Depending @@ -51,11 +49,10 @@ public sealed interface PowerValueSource< // non-sealed implementations /** Interface for time-series-based power value sources. */ - non-sealed interface TimeSeriesBased - extends PowerValueSource {} + non-sealed interface TimeSeriesBased extends PowerValueSource {} /** Interface for markov-chain-based power value sources. */ - non-sealed interface MarkovBased extends PowerValueSource {} + non-sealed interface MarkovBased extends PowerValueSource {} // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // input data @@ -66,7 +63,7 @@ non-sealed interface MarkovBased extends PowerValueSource loadProfileMetaInformation; + protected Map loadProfileMetaInformation; /** * Get a mapping from time series {@link UUID} to its meta information {@link @@ -41,7 +42,7 @@ public abstract Optional getTimeSeriesMetaI * * @return that mapping */ - public Map getLoadProfileMetaInformation() { + public Map getLoadProfileMetaInformation() { return Collections.unmodifiableMap(loadProfileMetaInformation); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java index 030194c08e..1f8f6891fa 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java @@ -10,14 +10,11 @@ import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.connectors.CsvFileConnector; import edu.ie3.datamodel.io.naming.FileNamingStrategy; -import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; -import edu.ie3.datamodel.io.naming.timeseries.FileIndividualTimeSeriesMetaInformation; -import edu.ie3.datamodel.io.naming.timeseries.FileLoadProfileMetaInformation; -import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation; -import edu.ie3.datamodel.io.naming.timeseries.TimeSeriesMetaInformation; +import edu.ie3.datamodel.io.naming.timeseries.*; import edu.ie3.datamodel.io.source.file.FileDataSource; import edu.ie3.datamodel.models.Entity; import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; import edu.ie3.datamodel.utils.Try.Success; @@ -126,11 +123,11 @@ public Stream> getSourceData(Path filePath) throws SourceExc * * @return A mapping from profile to the load profile time series meta information */ - public Map getCsvLoadProfileMetaInformation( + public Map getCsvLoadProfileMetaInformation( LoadProfile... profiles) { return getLoadProfileMetaInformation(profiles) .filter(metaInformation -> metaInformation.getFileType() == CSV) - .collect(Collectors.toMap(LoadProfileMetaInformation::getProfile, Function.identity())); + .collect(Collectors.toMap(LoadProfileMetaInformation::getProfileKey, Function.identity())); } /** diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java index 544b0e3187..f34242cd28 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java @@ -11,14 +11,15 @@ import edu.ie3.datamodel.io.factory.timeseries.LoadProfileFactory; import edu.ie3.datamodel.io.naming.timeseries.FileLoadProfileMetaInformation; import edu.ie3.datamodel.io.source.LoadProfileSource; -import edu.ie3.datamodel.models.profile.LoadProfile; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.load.LoadValues; import edu.ie3.datamodel.utils.Try; import java.nio.file.Path; -import java.util.*; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -29,9 +30,8 @@ /** * Source that is capable of providing information around load profile time series from csv files. */ -public class CsvLoadProfileSource

> - extends LoadProfileSource { - private final LoadProfileTimeSeries loadProfileTimeSeries; +public class CsvLoadProfileSource extends LoadProfileSource { + private final LoadProfileTimeSeries loadProfileTimeSeries; private final CsvDataSource dataSource; private final Path filePath; @@ -39,7 +39,7 @@ public CsvLoadProfileSource( CsvDataSource source, FileLoadProfileMetaInformation metaInformation, Class entryClass, - LoadProfileFactory entryFactory) { + LoadProfileFactory entryFactory) { super(metaInformation, entryClass, entryFactory); this.dataSource = source; this.filePath = metaInformation.getFullFilePath(); @@ -50,7 +50,7 @@ public CsvLoadProfileSource( } catch (SourceException e) { throw new IllegalArgumentException( "Unable to obtain load profile time series with profile '" - + metaInformation.getProfile() + + metaInformation.getProfileKey().getValue() + "'. Please check arguments!", e); } @@ -61,7 +61,7 @@ public void validate() throws ValidationException { validate(entryClass, () -> dataSource.getSourceFields(filePath), entryFactory); } - public LoadProfileTimeSeries getTimeSeries() { + public LoadProfileTimeSeries getTimeSeries() { return loadProfileTimeSeries; } @@ -97,7 +97,7 @@ public Optional> getProfileEnergyScaling() { * @throws SourceException If the file cannot be read properly * @return an individual time series */ - protected LoadProfileTimeSeries buildLoadProfileTimeSeries( + protected LoadProfileTimeSeries buildLoadProfileTimeSeries( Function, Try, FactoryException>> fieldToValueFunction) throws SourceException { @@ -111,6 +111,6 @@ protected LoadProfileTimeSeries buildLoadProfileTimeSeries( .getOrThrow() .collect(Collectors.toSet()); - return entryFactory.build(profile, entries); + return entryFactory.build(powerProfileKey, entries); } } diff --git a/src/main/java/edu/ie3/datamodel/io/source/file/FileDataSource.java b/src/main/java/edu/ie3/datamodel/io/source/file/FileDataSource.java index 526dc9229c..e0a0789801 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/file/FileDataSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/file/FileDataSource.java @@ -108,15 +108,14 @@ public Stream getLoadProfileMetaInformation( fileNamingStrategy.loadProfileTimeSeriesMetaInformation( fileMeta.filePath().toString()); return new FileLoadProfileMetaInformation( - metaInformation.getProfile(), fileMeta.pathWithoutEnding(), fileMeta.fileType()); + metaInformation, fileMeta.pathWithoutEnding(), fileMeta.fileType()); }) .filter( metaInformation -> profiles == null || profiles.length == 0 || Stream.of(profiles) - .anyMatch( - profile -> profile.getKey().equals(metaInformation.getProfile()))); + .anyMatch(profile -> metaInformation.getProfileKey().equals(profile))); } private Optional resolveFileInformation(Path filePath, String metaType) { diff --git a/src/main/java/edu/ie3/datamodel/io/source/file/FileTimeSeriesMetaInformationSource.java b/src/main/java/edu/ie3/datamodel/io/source/file/FileTimeSeriesMetaInformationSource.java index 34db88e581..a654e0fcd3 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/file/FileTimeSeriesMetaInformationSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/file/FileTimeSeriesMetaInformationSource.java @@ -59,7 +59,8 @@ public FileTimeSeriesMetaInformationSource(FileDataSource dataSource) { this.loadProfileMetaInformation = dataSource .getLoadProfileMetaInformation() - .collect(Collectors.toMap(LoadProfileMetaInformation::getProfile, Function.identity())); + .collect( + Collectors.toMap(LoadProfileMetaInformation::getProfileKey, Function.identity())); } @Override diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSource.java index 2af0e70356..479b190aaa 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSource.java @@ -13,7 +13,6 @@ import edu.ie3.datamodel.io.naming.DatabaseNamingStrategy; import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation; import edu.ie3.datamodel.io.source.LoadProfileSource; -import edu.ie3.datamodel.models.profile.LoadProfile; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries; import edu.ie3.datamodel.models.value.PValue; @@ -35,11 +34,9 @@ /** * Sql source for {@link LoadProfileTimeSeries}. * - * @param

type of load profile * @param type of load values */ -public class SqlLoadProfileSource

> - extends LoadProfileSource { +public class SqlLoadProfileSource extends LoadProfileSource { protected static final Logger log = LoggerFactory.getLogger(SqlLoadProfileSource.class); private final SqlDataSource dataSource; private final String tableName; @@ -60,7 +57,7 @@ public SqlLoadProfileSource( SqlDataSource dataSource, LoadProfileMetaInformation metaInformation, Class entryClass, - LoadProfileFactory entryFactory) { + LoadProfileFactory entryFactory) { super(metaInformation, entryClass, entryFactory); this.dataSource = dataSource; @@ -79,7 +76,7 @@ public SqlLoadProfileSource( DatabaseNamingStrategy namingStrategy, LoadProfileMetaInformation metaInformation, Class entryClass, - LoadProfileFactory entryFactory) { + LoadProfileFactory entryFactory) { this( new SqlDataSource(connector, schemaName, namingStrategy), metaInformation, @@ -102,20 +99,20 @@ public Set> getEntries() { @Override public Supplier> getValueSupplier(TimeSeriesInputValue data) { ZonedDateTime time = data.time(); - Optional> loadValueOption = queryForValue(time); - return () -> loadValueOption.map(v -> v.getValue(time, profile)); + Optional loadValueOption = queryForValue(time); + return () -> loadValueOption.map(v -> v.getValue(time, powerProfileKey)); } @Override public Optional> getMaxPower() { // TODO: Improve this calculation return Optional.ofNullable( - entryFactory.calculateMaxPower(profile, getEntries(queryFull, ps -> {}))); + entryFactory.calculateMaxPower(powerProfileKey, getEntries(queryFull, ps -> {}))); } @Override public Optional> getProfileEnergyScaling() { - return Optional.ofNullable(entryFactory.getLoadProfileEnergyScaling(profile)); + return Optional.ofNullable(entryFactory.getLoadProfileEnergyScaling(powerProfileKey)); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -135,7 +132,7 @@ private Set> getEntries(String query, SqlDataSource.AddParam .collect(Collectors.toSet()); } - private Optional> queryForValue(ZonedDateTime time) { + private Optional queryForValue(ZonedDateTime time) { Set> entries = getEntries(queryTime, ps -> ps.setInt(1, TimeSeriesUtils.calculateQuarterHourOfDay(time))); if (entries.isEmpty()) return Optional.empty(); @@ -169,7 +166,7 @@ private String createQueryFull(String schemaName, String tableName) { + WHERE + LOAD_PROFILE + " = '" - + profile.getKey() + + powerProfileKey.getValue() + "'"; } @@ -188,7 +185,7 @@ private String createQueryForTime(String schemaName, String tableName, String ti + WHERE + LOAD_PROFILE + " = '" - + profile.getKey() + + powerProfileKey.getValue() + "' AND " + timeColumnName + "=?;"; diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSource.java index ffdc47c7ac..f729cee3d0 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSource.java @@ -54,7 +54,8 @@ public SqlTimeSeriesMetaInformationSource( .executeQuery(loadMetaInformationQuery) .map(this::createLoadProfileEntity) .flatMap(Optional::stream) - .collect(Collectors.toMap(LoadProfileMetaInformation::getProfile, Function.identity())); + .collect( + Collectors.toMap(LoadProfileMetaInformation::getProfileKey, Function.identity())); } /** diff --git a/src/main/java/edu/ie3/datamodel/models/input/system/LoadInput.java b/src/main/java/edu/ie3/datamodel/models/input/system/LoadInput.java index 6beeba7d92..03f64a76cb 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/system/LoadInput.java +++ b/src/main/java/edu/ie3/datamodel/models/input/system/LoadInput.java @@ -11,8 +11,7 @@ import edu.ie3.datamodel.models.input.NodeInput; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.models.input.system.characteristic.ReactivePowerCharacteristic; -import edu.ie3.datamodel.models.profile.LoadProfile; -import edu.ie3.datamodel.models.profile.StandardLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.repetitive.RepetitiveTimeSeries; import java.util.Objects; @@ -29,7 +28,7 @@ public class LoadInput extends SystemParticipantInput { * external mapping (e.g. by providing a global time series for a specific load profile) to this * model */ - private final LoadProfile loadProfile; + private final PowerProfileKey loadProfile; /** Annually consumed energy (typically in kWh) */ private final ComparableQuantity eConsAnnual; @@ -50,7 +49,7 @@ public class LoadInput extends SystemParticipantInput { * @param node the asset is connected to * @param qCharacteristics Description of a reactive power characteristic * @param em The {@link EmInput} controlling this system participant. Null, if not applicable. - * @param loadProfile Load profile to use for this model + * @param powerProfileKey Key of the load profile to use for this model * @param eConsAnnual Annually consumed energy (typically in kWh) * @param sRated Rated apparent power (in kVA) * @param cosPhiRated Rated power factor @@ -63,12 +62,12 @@ public LoadInput( NodeInput node, ReactivePowerCharacteristic qCharacteristics, EmInput em, - LoadProfile loadProfile, + PowerProfileKey powerProfileKey, ComparableQuantity eConsAnnual, ComparableQuantity sRated, double cosPhiRated) { super(uuid, id, operator, operationTime, node, qCharacteristics, em); - this.loadProfile = loadProfile; + this.loadProfile = powerProfileKey; this.eConsAnnual = eConsAnnual.to(StandardUnits.ENERGY_IN); this.sRated = sRated.to(StandardUnits.S_RATED); this.cosPhiRated = cosPhiRated; @@ -102,9 +101,7 @@ public LoadInput( String loadProfileKey, ComparableQuantity eConsAnnual, ComparableQuantity sRated, - double cosPhiRated) - throws ParsingException { - + double cosPhiRated) { this( uuid, id, @@ -113,7 +110,7 @@ public LoadInput( node, qCharacteristics, em, - LoadProfile.parse(loadProfileKey), + new PowerProfileKey(loadProfileKey), eConsAnnual, sRated, cosPhiRated); @@ -127,7 +124,7 @@ public LoadInput( * @param node the asset is connected to * @param qCharacteristics Description of a reactive power characteristic * @param em The {@link EmInput} controlling this system participant. Null, if not applicable. - * @param loadProfile Standard load profile to use for this model + * @param powerProfileKey Key of a load profile to use for this model * @param eConsAnnual Annually consumed energy (typically in kWh) * @param sRated Rated apparent power (in kVA) * @param cosPhiRated Rated power factor @@ -138,12 +135,12 @@ public LoadInput( NodeInput node, ReactivePowerCharacteristic qCharacteristics, EmInput em, - LoadProfile loadProfile, + PowerProfileKey powerProfileKey, ComparableQuantity eConsAnnual, ComparableQuantity sRated, double cosPhiRated) { super(uuid, id, node, qCharacteristics, em); - this.loadProfile = loadProfile; + this.loadProfile = powerProfileKey; this.eConsAnnual = eConsAnnual.to(StandardUnits.ENERGY_IN); this.sRated = sRated.to(StandardUnits.S_RATED); this.cosPhiRated = cosPhiRated; @@ -157,9 +154,7 @@ public LoadInput( * @param node the asset is connected to * @param qCharacteristics Description of a reactive power characteristic * @param em The {@link EmInput} controlling this system participant. Null, if not applicable. - * @param loadProfileKey load profile key corresponding to {@link - * edu.ie3.datamodel.models.profile.BdewStandardLoadProfile} or {@link - * edu.ie3.datamodel.models.profile.NbwTemperatureDependantLoadProfile} + * @param powerProfileKey load profile key corresponding to a load profile * @param eConsAnnual Annually consumed energy (typically in kWh) * @param sRated Rated apparent power (in kVA) * @param cosPhiRated Rated power factor @@ -170,7 +165,7 @@ public LoadInput( NodeInput node, ReactivePowerCharacteristic qCharacteristics, EmInput em, - String loadProfileKey, + String powerProfileKey, ComparableQuantity eConsAnnual, ComparableQuantity sRated, double cosPhiRated) @@ -181,13 +176,13 @@ public LoadInput( node, qCharacteristics, em, - LoadProfile.parse(loadProfileKey), + new PowerProfileKey(powerProfileKey), eConsAnnual, sRated, cosPhiRated); } - public LoadProfile getLoadProfile() { + public PowerProfileKey getLoadProfile() { return loadProfile; } @@ -225,11 +220,19 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(super.hashCode(), eConsAnnual, sRated, cosPhiRated); + return Objects.hash(super.hashCode(), eConsAnnual, sRated, cosPhiRated, loadProfile); } @Override public String toString() { + String key; + + if (loadProfile == null) { + key = null; + } else { + key = loadProfile.getValue(); + } + return "LoadInput{" + "uuid=" + getUuid() @@ -245,6 +248,8 @@ public String toString() { + getqCharacteristics() + "', em=" + getControllingEm() + + ", loadProfile='" + + key + ", eConsAnnual=" + eConsAnnual + ", sRated=" @@ -264,21 +269,21 @@ public String toString() { public static class LoadInputCopyBuilder extends SystemParticipantInputCopyBuilder { - private LoadProfile loadProfile; + private PowerProfileKey powerProfileKey; private ComparableQuantity eConsAnnual; private ComparableQuantity sRated; private double cosPhiRated; private LoadInputCopyBuilder(LoadInput entity) { super(entity); - this.loadProfile = entity.getLoadProfile(); + this.powerProfileKey = entity.getLoadProfile(); this.eConsAnnual = entity.geteConsAnnual(); this.sRated = entity.getsRated(); this.cosPhiRated = entity.getCosPhiRated(); } - public LoadInputCopyBuilder loadprofile(StandardLoadProfile standardLoadProfile) { - this.loadProfile = standardLoadProfile; + public LoadInputCopyBuilder loadProfile(PowerProfileKey powerProfileKey) { + this.powerProfileKey = powerProfileKey; return thisInstance(); } @@ -314,7 +319,7 @@ public LoadInput build() { getNode(), getqCharacteristics(), getEm(), - loadProfile, + powerProfileKey, eConsAnnual, sRated, cosPhiRated); diff --git a/src/main/java/edu/ie3/datamodel/models/profile/BdewStandardLoadProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/BdewStandardLoadProfile.java index cac7ff8a79..dd715c707a 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/BdewStandardLoadProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/BdewStandardLoadProfile.java @@ -5,8 +5,6 @@ */ package edu.ie3.datamodel.models.profile; -import edu.ie3.datamodel.exceptions.ParsingException; - /** * German standard electricity load profiles, defined by the bdew (Bundesverband der Energie- und * Wasserwirtschaft; engl.Federal Association of the Energy and Water Industry). For more details @@ -30,25 +28,14 @@ public enum BdewStandardLoadProfile implements StandardLoadProfile { P25("p25"), // PV profile S25("s25"); // Combined PV and storage profile - private final String key; + private final PowerProfileKey key; BdewStandardLoadProfile(String key) { - this.key = key.toLowerCase(); - } - - /** - * Get the predefined bdew load profile based on the given key - * - * @param key key to check for - * @return The corresponding bdew load profile or throw {@link IllegalArgumentException}, if no - * matching load profile can be found - */ - public static BdewStandardLoadProfile get(String key) throws ParsingException { - return LoadProfile.getProfile(BdewStandardLoadProfile.values(), key); + this.key = new PowerProfileKey(key); } @Override - public String getKey() { + public PowerProfileKey getKey() { return key; } diff --git a/src/main/java/edu/ie3/datamodel/models/profile/LoadProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/LoadProfile.java index 4a28473057..bf76dfbdbd 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/LoadProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/LoadProfile.java @@ -5,76 +5,14 @@ */ package edu.ie3.datamodel.models.profile; -import edu.ie3.datamodel.exceptions.ParsingException; -import java.util.Arrays; -import java.util.stream.Collectors; -import java.util.stream.Stream; - public interface LoadProfile extends PowerProfile { - /** - * Parses the given key to {@link StandardLoadProfile}. - * - * @param key Key to parse - * @return Matching {@link StandardLoadProfile} - * @throws ParsingException If key cannot be parsed - */ - static LoadProfile parse(String key) throws ParsingException { - if (key == null || key.isEmpty()) return LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE; - - return LoadProfile.getProfile(getAllProfiles(), key); - } - - static LoadProfile[] getAllProfiles() { - return Stream.of( - BdewStandardLoadProfile.values(), - NbwTemperatureDependantLoadProfile.values(), - (LoadProfile[]) RandomLoadProfile.values()) - .flatMap(Arrays::stream) - .toArray(LoadProfile[]::new); - } - - /** - * Looks for load profile with given key and returns it. - * - * @param profiles we search within - * @param key to look for - * @return the matching load profile - */ - static T getProfile(T[] profiles, String key) throws ParsingException { - return Arrays.stream(profiles) - .filter(loadProfile -> loadProfile.getKey().equalsIgnoreCase(getUniformKey(key))) - .findFirst() - .orElseThrow( - () -> - new ParsingException( - "No predefined load profile with key '" - + key - + "' found. Please provide one of the following keys: " - + Arrays.stream(profiles) - .map(LoadProfile::getKey) - .collect(Collectors.joining(", ")))); - } - - private static String getUniformKey(String key) { - return key.toLowerCase().replaceAll("[-_]*", ""); - } - - enum DefaultLoadProfiles implements LoadProfile { - NO_LOAD_PROFILE; - - @Override - public String getKey() { - return "No load profile assigned"; - } - } - enum RandomLoadProfile implements LoadProfile { RANDOM_LOAD_PROFILE; @Override - public String getKey() { - return "random"; + public PowerProfileKey getKey() { + return new PowerProfileKey("random"); } } } diff --git a/src/main/java/edu/ie3/datamodel/models/profile/NbwTemperatureDependantLoadProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/NbwTemperatureDependantLoadProfile.java index 783e164bc5..f07d5674fd 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/NbwTemperatureDependantLoadProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/NbwTemperatureDependantLoadProfile.java @@ -5,8 +5,6 @@ */ package edu.ie3.datamodel.models.profile; -import edu.ie3.datamodel.exceptions.ParsingException; - /** Temperature dependant determined by NBW (accessed 05/2022) */ public enum NbwTemperatureDependantLoadProfile implements TemperatureDependantLoadProfile { // heat pumps @@ -15,25 +13,14 @@ public enum NbwTemperatureDependantLoadProfile implements TemperatureDependantLo // night storage heating EZ2("ez2"); - private final String key; + private final PowerProfileKey key; NbwTemperatureDependantLoadProfile(String key) { - this.key = key.toLowerCase(); - } - - /** - * Get the predefined nbw load profile based on the given key - * - * @param key key to check for - * @return The corresponding nbw load profile or throw {@link IllegalArgumentException}, if no - * matching load profile can be found - */ - public static NbwTemperatureDependantLoadProfile get(String key) throws ParsingException { - return LoadProfile.getProfile(NbwTemperatureDependantLoadProfile.values(), key); + this.key = new PowerProfileKey(key); } @Override - public String getKey() { + public PowerProfileKey getKey() { return this.key; } diff --git a/src/main/java/edu/ie3/datamodel/models/profile/PowerProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfile.java index a39a3ae0e4..5566fd8fba 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/PowerProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfile.java @@ -13,5 +13,5 @@ public interface PowerProfile extends Serializable { /** * @return The identifying String */ - String getKey(); + PowerProfileKey getKey(); } diff --git a/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java new file mode 100644 index 0000000000..a753b0adae --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java @@ -0,0 +1,68 @@ +/* + * © 2025. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.profile; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +/** Interface defining a power profile. */ +public final class PowerProfileKey implements Serializable { + + private final String value; + public final boolean noKeyAssigned; + + public PowerProfileKey(String key) { + if (key == null || key.isEmpty()) { + this.value = "No profile assigned."; + this.noKeyAssigned = true; + } else { + this.value = toUniformKey(key); + this.noKeyAssigned = false; + } + } + + public String getValue() { + return value; + } + + public boolean equals(PowerProfile other) { + return equals(other.getKey()); + } + + public boolean equalsAny(PowerProfile... others) { + return Arrays.stream(others).anyMatch(this::equals); + } + + private boolean equals(String other) { + return value.equalsIgnoreCase(toUniformKey(other)); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + PowerProfileKey that = (PowerProfileKey) o; + return noKeyAssigned == that.noKeyAssigned && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(value, noKeyAssigned); + } + + @Override + public String toString() { + return "PowerProfileKey{" + "value='" + value + '\'' + ", noKeyAssigned=" + noKeyAssigned + '}'; + } + + // static + + public static final PowerProfileKey NO_KEY_ASSIGNED = new PowerProfileKey(""); + + public static String toUniformKey(String key) { + return key.toLowerCase().replaceAll("[-_]*", ""); + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/profile/StandardLoadProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/StandardLoadProfile.java index b2878df099..22fd9c23b6 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/StandardLoadProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/StandardLoadProfile.java @@ -5,7 +5,6 @@ */ package edu.ie3.datamodel.models.profile; -import edu.ie3.datamodel.exceptions.ParsingException; import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.repetitive.RepetitiveTimeSeries; @@ -17,15 +16,4 @@ *

If you intend to provide distinct values, create either an {@link IndividualTimeSeries} or * {@link RepetitiveTimeSeries} and assign it to the model via mapping to the model. */ -public interface StandardLoadProfile extends LoadProfile { - - /** - * Returns standard load profile corresponding to the given key. - * - * @param key to look for - * @return the matching standard load profile - */ - static StandardLoadProfile parse(String key) throws ParsingException { - return LoadProfile.getProfile(BdewStandardLoadProfile.values(), key); - } -} +public interface StandardLoadProfile extends LoadProfile {} diff --git a/src/main/java/edu/ie3/datamodel/models/profile/TemperatureDependantLoadProfile.java b/src/main/java/edu/ie3/datamodel/models/profile/TemperatureDependantLoadProfile.java index 4b5a94f200..34f17745fd 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/TemperatureDependantLoadProfile.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/TemperatureDependantLoadProfile.java @@ -5,22 +5,9 @@ */ package edu.ie3.datamodel.models.profile; -import edu.ie3.datamodel.exceptions.ParsingException; - /** * Temperature dependant load profiles for night storage heating and heat pumps . The profiles rely * on the VDN description for interruptable loads. For more details see here. */ -public interface TemperatureDependantLoadProfile extends LoadProfile { - - /** - * Returns temperature dependant load profile corresponding to the given key. - * - * @param key to look for - * @return the matching temperature dependant load profile - */ - static TemperatureDependantLoadProfile parse(String key) throws ParsingException { - return LoadProfile.getProfile(NbwTemperatureDependantLoadProfile.values(), key); - } -} +public interface TemperatureDependantLoadProfile extends LoadProfile {} diff --git a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java index 8601a5a8bf..0da24a8c0d 100644 --- a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java +++ b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java @@ -5,7 +5,7 @@ */ package edu.ie3.datamodel.models.timeseries.repetitive; -import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.load.BdewLoadValues; import java.util.Objects; import java.util.Set; @@ -17,15 +17,14 @@ * Describes a bdew load profile time series with repetitive values that can be calculated from a * pattern. Each value of this timeseries is given in W. */ -public class BdewLoadProfileTimeSeries - extends LoadProfileTimeSeries { +public class BdewLoadProfileTimeSeries extends LoadProfileTimeSeries { public BdewLoadProfileTimeSeries( - BdewStandardLoadProfile loadProfile, + PowerProfileKey powerProfileKey, Set> values, ComparableQuantity maxPower, ComparableQuantity profileEnergyScaling) { - super(loadProfile, values, maxPower, profileEnergyScaling); + super(powerProfileKey, values, maxPower, profileEnergyScaling); } @Override @@ -43,8 +42,8 @@ public int hashCode() { @Override public String toString() { return "BDEWLoadProfileTimeSeries{" - + "loadProfile=" - + getLoadProfile() + + "loadProfileKey=" + + getPowerProfileKey().getValue() + ", valueMapping=" + getValueMapping() + '}'; diff --git a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/LoadProfileTimeSeries.java b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/LoadProfileTimeSeries.java index d3c72ea15c..91b2e616ec 100644 --- a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/LoadProfileTimeSeries.java +++ b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/LoadProfileTimeSeries.java @@ -5,7 +5,7 @@ */ package edu.ie3.datamodel.models.timeseries.repetitive; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.load.LoadValues; import edu.ie3.datamodel.utils.TimeSeriesUtils; @@ -20,9 +20,9 @@ /** * Describes a load profile time series with repetitive values that can be calculated from a pattern */ -public class LoadProfileTimeSeries

> +public class LoadProfileTimeSeries extends RepetitiveTimeSeries, V, PValue> { - protected final P loadProfile; + protected final PowerProfileKey powerProfileKey; protected final Map valueMapping; /** @@ -35,12 +35,12 @@ public class LoadProfileTimeSeries

profileEnergyScaling; public LoadProfileTimeSeries( - P loadProfile, + PowerProfileKey powerProfileKey, Set> entries, ComparableQuantity maxPower, ComparableQuantity profileEnergyScaling) { super(entries); - this.loadProfile = loadProfile; + this.powerProfileKey = powerProfileKey; this.valueMapping = entries.stream() .collect( @@ -63,9 +63,9 @@ public Optional> loadProfileScaling() { return Optional.ofNullable(profileEnergyScaling); } - /** Returns the {@link LoadProfile}. */ - public P getLoadProfile() { - return loadProfile; + /** Returns the {@link PowerProfileKey}. */ + public PowerProfileKey getPowerProfileKey() { + return powerProfileKey; } @Override @@ -87,8 +87,8 @@ public Set> getEntries() { */ public Supplier> supplyValue(ZonedDateTime time) { int quarterHour = TimeSeriesUtils.calculateQuarterHourOfDay(time); - LoadValues

loadValue = valueMapping.get(quarterHour); - return () -> Optional.ofNullable(loadValue.getValue(time, loadProfile)); + LoadValues loadValue = valueMapping.get(quarterHour); + return () -> Optional.ofNullable(loadValue.getValue(time, powerProfileKey)); } @Override @@ -109,7 +109,7 @@ protected Map getValueMapping() { @Override protected PValue calc(ZonedDateTime time) { int quarterHour = TimeSeriesUtils.calculateQuarterHourOfDay(time); - return valueMapping.get(quarterHour).getValue(time, loadProfile); + return valueMapping.get(quarterHour).getValue(time, powerProfileKey); } @Override @@ -117,8 +117,8 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; - LoadProfileTimeSeries that = (LoadProfileTimeSeries) o; - return loadProfile.equals(that.loadProfile) && valueMapping.equals(that.valueMapping); + LoadProfileTimeSeries that = (LoadProfileTimeSeries) o; + return powerProfileKey.equals(that.powerProfileKey) && valueMapping.equals(that.valueMapping); } @Override @@ -130,7 +130,7 @@ public int hashCode() { public String toString() { return "LoadProfileTimeSeries{" + "loadProfile=" - + getLoadProfile() + + getPowerProfileKey().getValue() + ", valueMapping=" + getValueMapping() + '}'; diff --git a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/RandomLoadProfileTimeSeries.java b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/RandomLoadProfileTimeSeries.java index 4e6da05b15..a5dfca6e63 100644 --- a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/RandomLoadProfileTimeSeries.java +++ b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/RandomLoadProfileTimeSeries.java @@ -6,7 +6,7 @@ package edu.ie3.datamodel.models.timeseries.repetitive; import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.load.RandomLoadValues; import java.util.Set; import javax.measure.quantity.Energy; @@ -17,15 +17,14 @@ * Describes a random load profile time series based on a {@link * GeneralizedExtremeValueDistribution}. Each value of this# timeseries is given in kW. */ -public class RandomLoadProfileTimeSeries - extends LoadProfileTimeSeries { +public class RandomLoadProfileTimeSeries extends LoadProfileTimeSeries { public RandomLoadProfileTimeSeries( - LoadProfile.RandomLoadProfile loadProfile, + PowerProfileKey powerProfileKey, Set> entries, ComparableQuantity maxPower, ComparableQuantity profileEnergyScaling) { - super(loadProfile, entries, maxPower, profileEnergyScaling); + super(powerProfileKey, entries, maxPower, profileEnergyScaling); } @Override diff --git a/src/main/java/edu/ie3/datamodel/models/value/load/BdewLoadValues.java b/src/main/java/edu/ie3/datamodel/models/value/load/BdewLoadValues.java index bd6f5bb73b..302a14ae2b 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/load/BdewLoadValues.java +++ b/src/main/java/edu/ie3/datamodel/models/value/load/BdewLoadValues.java @@ -5,6 +5,7 @@ */ package edu.ie3.datamodel.models.value.load; +import static edu.ie3.datamodel.models.profile.BdewStandardLoadProfile.*; import static edu.ie3.datamodel.models.value.load.BdewLoadValues.BdewSeason.WINTER; import static edu.ie3.datamodel.models.value.load.BdewLoadValues.BdewSeason.getSeason; import static java.lang.Math.pow; @@ -14,6 +15,7 @@ import edu.ie3.datamodel.exceptions.ParsingException; import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.PValue; import java.io.*; import java.time.Month; @@ -26,7 +28,7 @@ import tech.units.indriya.quantity.Quantities; /** Load values for a {@link BdewStandardLoadProfile} */ -public final class BdewLoadValues implements LoadValues { +public final class BdewLoadValues implements LoadValues { public final BdewScheme scheme; private transient Map values; @@ -104,14 +106,15 @@ public double getMaxValue(boolean lastDayOfYear) { } @Override - public PValue getValue(ZonedDateTime time, BdewStandardLoadProfile loadProfile) { - double power = - switch (loadProfile) { - case H0, H25, P25, S25 -> - /* For the residential average profile, a dynamization has to be taken into account */ - dynamization(getPower(time), time.getDayOfYear()); // leap years are ignored - default -> getPower(time); - }; + public PValue getValue(ZonedDateTime time, PowerProfileKey powerProfileKey) { + double power; + + if (powerProfileKey.equalsAny(H0, H25, P25, S25)) { + /* For the residential average profile, a dynamization has to be taken into account */ + power = dynamization(getPower(time), time.getDayOfYear()); // leap years are ignored + } else { + power = getPower(time); + } return new PValue(Quantities.getQuantity(power, WATT)); } @@ -464,8 +467,8 @@ public Collection values() { * Maps the {@link BdewKey} to a new value. * * @param mapper function - * @return the new {@link BdewMap} * @param type of new values + * @return the new {@link BdewMap} */ public Map map(Function mapper) { HashMap map = new HashMap<>(); diff --git a/src/main/java/edu/ie3/datamodel/models/value/load/LoadValues.java b/src/main/java/edu/ie3/datamodel/models/value/load/LoadValues.java index 9c35c7c53c..70a64e2894 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/load/LoadValues.java +++ b/src/main/java/edu/ie3/datamodel/models/value/load/LoadValues.java @@ -5,14 +5,14 @@ */ package edu.ie3.datamodel.models.value.load; -import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; import java.time.ZonedDateTime; import java.util.Optional; /** Interface for load values. */ -public interface LoadValues

extends Value { +public interface LoadValues extends Value { /** * Method to calculate an actual load power value for the given time. @@ -20,7 +20,7 @@ public interface LoadValues

extends Value { * @param time given time * @return a new {@link PValue} */ - PValue getValue(ZonedDateTime time, P loadProfile); + PValue getValue(ZonedDateTime time, PowerProfileKey loadProfile); /** Returns the {@link Scheme} of the underlying values. */ default Optional getScheme() { diff --git a/src/main/java/edu/ie3/datamodel/models/value/load/RandomLoadValues.java b/src/main/java/edu/ie3/datamodel/models/value/load/RandomLoadValues.java index 109b175fd5..48b9850133 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/load/RandomLoadValues.java +++ b/src/main/java/edu/ie3/datamodel/models/value/load/RandomLoadValues.java @@ -9,7 +9,7 @@ import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution; import de.lmu.ifi.dbs.elki.utilities.random.RandomFactory; -import edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile; +import edu.ie3.datamodel.models.profile.PowerProfileKey; import edu.ie3.datamodel.models.value.PValue; import java.time.DayOfWeek; import java.time.ZonedDateTime; @@ -23,7 +23,7 @@ * sampled for each quarter hour of a day, subdivided into workdays, Saturdays and Sundays. In * general the GEV is described by the three parameters "location", "scale" and "shape" */ -public class RandomLoadValues implements LoadValues { +public class RandomLoadValues implements LoadValues { /** Shape parameter for a Saturday */ private final double kSa; @@ -95,7 +95,7 @@ public RandomLoadValues( } @Override - public PValue getValue(ZonedDateTime time, RandomLoadProfile loadProfile) { + public PValue getValue(ZonedDateTime time, PowerProfileKey powerProfileKey) { return new PValue(Quantities.getQuantity(getValue(time.getDayOfWeek()), KILOWATT)); } diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java index 6a14d07755..e927dbd5fb 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java @@ -13,11 +13,9 @@ import edu.ie3.datamodel.models.input.UniqueInputEntity; import edu.ie3.datamodel.models.input.system.*; import edu.ie3.datamodel.models.input.system.type.*; -import edu.ie3.datamodel.models.profile.LoadProfile; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import javax.measure.Quantity; import javax.measure.quantity.Dimensionless; @@ -379,21 +377,7 @@ private static List> checkLoad(LoadInput loadI exceptions.add( Try.ofVoid( loadInput.getLoadProfile() == null, - () -> new InvalidEntityException("No load profile defined for load", loadInput))); - - if (loadInput.getLoadProfile() != null) { - LoadProfile profile = loadInput.getLoadProfile(); - - // Validate if the profile is one of the allowed profiles - exceptions.add( - Try.ofVoid( - !(profile.equals(LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE) - || Arrays.asList(LoadProfile.getAllProfiles()).contains(profile)), - () -> - new InvalidEntityException( - "Load profile must contain at least one valid entry: h0, g[0-6], l[0-2], ep1, ez2, random, or LoadProfile#NO_LOAD_PROFILE.", - loadInput))); - } + () -> new InvalidEntityException("No load profile key defined for load", loadInput))); // Check negative quantities and power factor exceptions.addAll( @@ -515,27 +499,22 @@ private static List> checkStorage(StorageInput */ private static List> checkStorageType( StorageTypeInput storageTypeInput) { - List> exceptions = new ArrayList<>(); - - exceptions.addAll( - Try.ofVoid( - InvalidEntityException.class, - () -> - isBetweenZeroAndHundredPercent( - storageTypeInput, - storageTypeInput.getEta(), - "Efficiency of the electrical converter"), - () -> - detectNegativeQuantities( - new Quantity[] { - storageTypeInput.getpMax(), storageTypeInput.getActivePowerGradient(), - }, - storageTypeInput), - () -> - detectZeroOrNegativeQuantities( - new Quantity[] {storageTypeInput.geteStorage()}, storageTypeInput))); - - return exceptions; + return Try.ofVoid( + InvalidEntityException.class, + () -> + isBetweenZeroAndHundredPercent( + storageTypeInput, + storageTypeInput.getEta(), + "Efficiency of the electrical converter"), + () -> + detectNegativeQuantities( + new Quantity[] { + storageTypeInput.getpMax(), storageTypeInput.getActivePowerGradient(), + }, + storageTypeInput), + () -> + detectZeroOrNegativeQuantities( + new Quantity[] {storageTypeInput.geteStorage()}, storageTypeInput)); } /** diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactoryTest.groovy index d3eaef18a0..71d354e6b6 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactoryTest.groovy @@ -78,7 +78,7 @@ class LoadInputFactoryTest extends Specification implements FactoryTestHelper { where: profileKey || profile - "G-4" || BdewStandardLoadProfile.G4 - "ep1" || NbwTemperatureDependantLoadProfile.EP1 + "G-4" || BdewStandardLoadProfile.G4.key + "ep1" || NbwTemperatureDependantLoadProfile.EP1.key } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactoryTest.groovy index e42bd120c7..9f90b6aafe 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactoryTest.groovy @@ -125,16 +125,16 @@ class BdewLoadProfileFactoryTest extends Specification { def "A BDEWLoadProfileFactory builds time series from entries"() { when: - def lpts = factory.build(BdewStandardLoadProfile.G0, allEntries) + def lpts = factory.build(BdewStandardLoadProfile.G0.key, allEntries) then: - lpts.loadProfile == BdewStandardLoadProfile.G0 + lpts.powerProfileKey == BdewStandardLoadProfile.G0.key lpts.entries.size() == 3 } def "A BDEWLoadProfileFactory does return the max power correctly"() { when: - def maxPower = factory.calculateMaxPower(BdewStandardLoadProfile.G0, allEntries) + def maxPower = factory.calculateMaxPower(BdewStandardLoadProfile.G0.key, allEntries) then: maxPower == Quantities.getQuantity(77.7, PowerSystemUnits.WATT) @@ -142,7 +142,7 @@ class BdewLoadProfileFactoryTest extends Specification { def "A BDEWLoadProfileFactory does return an energy scaling correctly"() { when: - def energyScaling = factory.getLoadProfileEnergyScaling(BdewStandardLoadProfile.G0) + def energyScaling = factory.getLoadProfileEnergyScaling(BdewStandardLoadProfile.G0.key) then: energyScaling == Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR) diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactoryTest.groovy index b3d2b54b44..5b4c4ab85c 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactoryTest.groovy @@ -131,16 +131,16 @@ class RandomLoadProfileFactoryTest extends Specification { def "A RandomLoadProfileFactory builds time series from entries"() { when: - def lpts = factory.build(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE, allEntries) + def lpts = factory.build(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE.key, allEntries) then: - lpts.loadProfile == LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE + lpts.powerProfileKey == LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE.key lpts.entries.size() == 3 } def "A RandomLoadProfileFactory does return the max power correctly"() { when: - def maxPower = factory.calculateMaxPower(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE, allEntries) + def maxPower = factory.calculateMaxPower(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE.key, allEntries) then: maxPower == Quantities.getQuantity(159d, PowerSystemUnits.WATT) @@ -148,7 +148,7 @@ class RandomLoadProfileFactoryTest extends Specification { def "A RandomLoadProfileFactory does return an energy scaling correctly"() { when: - def energyScaling = factory.getLoadProfileEnergyScaling(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE) + def energyScaling = factory.getLoadProfileEnergyScaling(LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE.key) then: energyScaling == Quantities.getQuantity(716.5416966513656, PowerSystemUnits.KILOWATTHOUR) diff --git a/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy index 8688aced04..1d221472fb 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy @@ -414,7 +414,7 @@ class EntityPersistenceNamingStrategyTest extends Specification { given: EntityPersistenceNamingStrategy strategy = new EntityPersistenceNamingStrategy() BdewLoadProfileTimeSeries timeSeries = Mock(BdewLoadProfileTimeSeries) - timeSeries.loadProfile >> type + timeSeries.powerProfileKey >> type when: Optional actual = strategy.getEntityName(timeSeries) @@ -424,8 +424,8 @@ class EntityPersistenceNamingStrategyTest extends Specification { actual.get() == expectedFileName where: - clazz | type || expectedFileName - BdewLoadProfileTimeSeries | BdewStandardLoadProfile.G3 || "lpts_g3" + clazz | type || expectedFileName + BdewLoadProfileTimeSeries | BdewStandardLoadProfile.G3.key || "lpts_g3" } def "A EntityPersistenceNamingStrategy returns empty Optional, when there is no naming defined for a given time series class"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/naming/FileNamingStrategyTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/naming/FileNamingStrategyTest.groovy index 3b12faef44..7ec48378b6 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/naming/FileNamingStrategyTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/naming/FileNamingStrategyTest.groovy @@ -402,7 +402,7 @@ class FileNamingStrategyTest extends Specification { given: def strategy = new FileNamingStrategy(simpleEntityNaming, defaultHierarchy) def timeSeries = Mock(LoadProfileTimeSeries) - timeSeries.loadProfile >> type + timeSeries.powerProfileKey >> type when: def actual = strategy.getFilePath(timeSeries) @@ -412,8 +412,8 @@ class FileNamingStrategyTest extends Specification { actual.get() == expectedFileName where: - clazz | type || expectedFileName - LoadProfileTimeSeries | BdewStandardLoadProfile.G3 || Path.of("test_grid", "input", "participants", "time_series", "lpts_g3") + clazz | type || expectedFileName + LoadProfileTimeSeries | BdewStandardLoadProfile.G3.key || Path.of("test_grid", "input", "participants", "time_series", "lpts_g3") } def "A FileNamingStrategy with DefaultHierarchy and without pre- or suffixes should return valid directory path for time series mapping"() { @@ -710,7 +710,7 @@ class FileNamingStrategyTest extends Specification { given: "a naming strategy without pre- or suffixes" def strategy = new FileNamingStrategy(simpleEntityNaming, flatHierarchy) def timeSeries = Mock(LoadProfileTimeSeries) - timeSeries.loadProfile >> type + timeSeries.powerProfileKey >> type when: def actual = strategy.getFilePath(timeSeries) @@ -720,8 +720,8 @@ class FileNamingStrategyTest extends Specification { actual.get() == expectedFilePath where: - clazz | type || expectedFilePath - LoadProfileTimeSeries | BdewStandardLoadProfile.G3 || Path.of("lpts_g3") + clazz | type || expectedFilePath + LoadProfileTimeSeries | BdewStandardLoadProfile.G3.key || Path.of("lpts_g3") } def "A FileNamingStrategy with FlatHierarchy does return valid file path for individual time series"() { @@ -919,7 +919,7 @@ class FileNamingStrategyTest extends Specification { then: LoadProfileMetaInformation.isAssignableFrom(metaInformation.getClass()) (metaInformation as LoadProfileMetaInformation).with { - assert profile == "g3" + assert profileKey.value == "g3" } } @@ -934,7 +934,7 @@ class FileNamingStrategyTest extends Specification { then: LoadProfileMetaInformation.isAssignableFrom(metaInformation.getClass()) (metaInformation as LoadProfileMetaInformation).with { - assert profile == "g3" + assert profileKey.value == "g3" } } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/processor/input/InputEntityProcessorTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/processor/input/InputEntityProcessorTest.groovy index e22ff1a992..9471854572 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/processor/input/InputEntityProcessorTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/processor/input/InputEntityProcessorTest.groovy @@ -246,7 +246,7 @@ class InputEntityProcessorTest extends Specification { "operator" : SystemParticipantTestData.loadInput.operator.uuid.toString(), "qCharacteristics" : SystemParticipantTestData.cosPhiFixedSerialized, "sRated" : SystemParticipantTestData.loadInput.sRated.getValue().doubleValue().toString(), - "loadProfile" : SystemParticipantTestData.loadInput.loadProfile.key, + "loadProfile" : SystemParticipantTestData.loadInput.loadProfile.value, "controllingEm" : SystemParticipantTestData.loadInput.controllingEm.map((UniqueEntity::getUuid).andThen(UUID::toString)).orElse("") ] StorageInput | SystemParticipantTestData.storageInput || [ diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/LoadProfileSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/LoadProfileSourceTest.groovy index 54270c5c47..cc363a6d6e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/LoadProfileSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/LoadProfileSourceTest.groovy @@ -9,20 +9,33 @@ import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RAN import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile import edu.ie3.datamodel.models.profile.LoadProfile +import edu.ie3.datamodel.models.profile.NbwTemperatureDependantLoadProfile +import edu.ie3.datamodel.models.profile.PowerProfileKey import spock.lang.Specification +import java.util.stream.Stream + class LoadProfileSourceTest extends Specification { def "A LoadProfileSource should return the correct profile resolution for a given load profile"() { given: - def allProfiles = LoadProfile.getAllProfiles() - + def allProfiles = Stream.of(BdewStandardLoadProfile.values(), NbwTemperatureDependantLoadProfile.values(), new LoadProfile[] { + RANDOM_LOAD_PROFILE + }).flatMap { + Arrays.stream(it) + } when: - def resolutions = Arrays.stream(allProfiles).map { it -> LoadProfileSource.getResolution(it) }.toList() + def resolutions = allProfiles.map { + it -> LoadProfileSource.getResolution(it.key) + }.toList() + def resolutionForNoKeyAssigned = LoadProfileSource.getResolution(PowerProfileKey.NO_KEY_ASSIGNED) then: - resolutions.every { resolution -> resolution == 900 } + resolutions.every { + resolution -> resolution == 900 + } + resolutionForNoKeyAssigned == Long.MAX_VALUE } @@ -32,8 +45,12 @@ class LoadProfileSourceTest extends Specification { then: profiles.size() == 16 - BdewStandardLoadProfile.values().every { profiles.keySet().contains(it) } - profiles.values().every { it.timeSeries.entries.size() == 96 } + BdewStandardLoadProfile.values().every { + profiles.keySet().contains(it.key) + } + profiles.values().every { + it.timeSeries.entries.size() == 96 + } } def "A LoadProfileSource should read in the build-in RandomLoadProfile"() { @@ -41,7 +58,7 @@ class LoadProfileSourceTest extends Specification { def random = LoadProfileSource.randomLoadProfile.timeSeries then: - random.loadProfile == RANDOM_LOAD_PROFILE + random.powerProfileKey == RANDOM_LOAD_PROFILE.key random.entries.size() == 96 } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy index 2dc883c513..4351c5a371 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy @@ -13,6 +13,7 @@ import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme import edu.ie3.datamodel.io.naming.timeseries.FileIndividualTimeSeriesMetaInformation import edu.ie3.datamodel.models.input.system.LoadInput import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile +import edu.ie3.datamodel.models.profile.PowerProfileKey import spock.lang.Shared import spock.lang.Specification @@ -422,9 +423,9 @@ class CsvDataSourceTest extends Specification implements CsvTestDataMeta { then: actual.size() == 3 - actual.get("r1").fullFilePath == Path.of("lpts_r1") - actual.get("r2").fullFilePath == Path.of("lpts_r2") - actual.get("g0").fullFilePath == Path.of("lpts_g0") + actual.get(new PowerProfileKey("r1")).fullFilePath == Path.of("lpts_r1") + actual.get(new PowerProfileKey("r2")).fullFilePath == Path.of("lpts_r2") + actual.get(new PowerProfileKey("g0")).fullFilePath == Path.of("lpts_g0") } def "The CsvDataSource is able to build correct load profile meta information when restricting load profile"() { @@ -433,6 +434,6 @@ class CsvDataSourceTest extends Specification implements CsvTestDataMeta { then: actual.size() == 1 - actual.get("g0").fullFilePath == Path.of("lpts_g0") + actual.get(new PowerProfileKey("g0")).fullFilePath == Path.of("lpts_g0") } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSourceIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSourceIT.groovy index 4e486db9bc..623bd5b5ec 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSourceIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlLoadProfileSourceIT.groovy @@ -34,7 +34,7 @@ class SqlLoadProfileSourceIT extends Specification implements TestContainerHelpe SqlConnector connector @Shared - SqlLoadProfileSource loadSource + SqlLoadProfileSource loadSource @Shared DatabaseNamingStrategy namingStrategy diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/system/LoadInputTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/system/LoadInputTest.groovy index 8694431b0f..92fed0df1f 100644 --- a/src/test/groovy/edu/ie3/datamodel/models/input/system/LoadInputTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/models/input/system/LoadInputTest.groovy @@ -23,7 +23,7 @@ class LoadInputTest extends Specification { def loadInput = SystemParticipantTestData.loadInput when: - def alteredUnit = loadInput.copy().loadprofile(BdewStandardLoadProfile.G0) + def alteredUnit = loadInput.copy().loadProfile(BdewStandardLoadProfile.G0.key) .eConsAnnual(Quantities.getQuantity(6000, KILOWATTHOUR)).sRated(Quantities.getQuantity(0d, KILOVOLTAMPERE)) .cosPhiRated(0.8).node(GridTestData.nodeG) .qCharacteristics(CosPhiFixed.CONSTANT_CHARACTERISTIC).build() @@ -34,7 +34,7 @@ class LoadInputTest extends Specification { assert operationTime == loadInput.operationTime assert operator == loadInput.operator assert id == loadInput.id - assert loadProfile == BdewStandardLoadProfile.G0 + assert loadProfile == BdewStandardLoadProfile.G0.key assert node == GridTestData.nodeG assert qCharacteristics == CosPhiFixed.CONSTANT_CHARACTERISTIC assert eConsAnnual == Quantities.getQuantity(6000, KILOWATTHOUR) diff --git a/src/test/groovy/edu/ie3/datamodel/models/profile/LoadProfileTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/profile/LoadProfileTest.groovy deleted file mode 100644 index a28d64bedc..0000000000 --- a/src/test/groovy/edu/ie3/datamodel/models/profile/LoadProfileTest.groovy +++ /dev/null @@ -1,222 +0,0 @@ -/* - * © 2021. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ -package edu.ie3.datamodel.models.profile - -import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE - -import edu.ie3.datamodel.exceptions.ParsingException -import spock.lang.Specification - -class LoadProfileTest extends Specification { - def "Load profiles are parsed correctly from correct input" () { - when: - LoadProfile actual = LoadProfile.parse(key) - - then: - actual == expected - - where: - key || expected - "h0" || BdewStandardLoadProfile.H0 - "h-0" || BdewStandardLoadProfile.H0 - "h_0" || BdewStandardLoadProfile.H0 - "H0" || BdewStandardLoadProfile.H0 - "H-0" || BdewStandardLoadProfile.H0 - "H_0" || BdewStandardLoadProfile.H0 - "h25" || BdewStandardLoadProfile.H25 - "h-25" || BdewStandardLoadProfile.H25 - "h_25" || BdewStandardLoadProfile.H25 - "H25" || BdewStandardLoadProfile.H25 - "H-25" || BdewStandardLoadProfile.H25 - "H_25" || BdewStandardLoadProfile.H25 - "l0" || BdewStandardLoadProfile.L0 - "l-0" || BdewStandardLoadProfile.L0 - "l_0" || BdewStandardLoadProfile.L0 - "L0" || BdewStandardLoadProfile.L0 - "L-0" || BdewStandardLoadProfile.L0 - "L_0" || BdewStandardLoadProfile.L0 - "l1" || BdewStandardLoadProfile.L1 - "l-1" || BdewStandardLoadProfile.L1 - "l_1" || BdewStandardLoadProfile.L1 - "L1" || BdewStandardLoadProfile.L1 - "L-1" || BdewStandardLoadProfile.L1 - "L_1" || BdewStandardLoadProfile.L1 - "l2" || BdewStandardLoadProfile.L2 - "l-2" || BdewStandardLoadProfile.L2 - "l_2" || BdewStandardLoadProfile.L2 - "L2" || BdewStandardLoadProfile.L2 - "L-2" || BdewStandardLoadProfile.L2 - "L_2" || BdewStandardLoadProfile.L2 - "l25" || BdewStandardLoadProfile.L25 - "l-25" || BdewStandardLoadProfile.L25 - "l_25" || BdewStandardLoadProfile.L25 - "L25" || BdewStandardLoadProfile.L25 - "L-25" || BdewStandardLoadProfile.L25 - "L_25" || BdewStandardLoadProfile.L25 - "g0" || BdewStandardLoadProfile.G0 - "g-0" || BdewStandardLoadProfile.G0 - "g_0" || BdewStandardLoadProfile.G0 - "G0" || BdewStandardLoadProfile.G0 - "G-0" || BdewStandardLoadProfile.G0 - "G_0" || BdewStandardLoadProfile.G0 - "g1" || BdewStandardLoadProfile.G1 - "g-1" || BdewStandardLoadProfile.G1 - "g_1" || BdewStandardLoadProfile.G1 - "G1" || BdewStandardLoadProfile.G1 - "G-1" || BdewStandardLoadProfile.G1 - "G_1" || BdewStandardLoadProfile.G1 - "g2" || BdewStandardLoadProfile.G2 - "g-2" || BdewStandardLoadProfile.G2 - "g_2" || BdewStandardLoadProfile.G2 - "G2" || BdewStandardLoadProfile.G2 - "G-2" || BdewStandardLoadProfile.G2 - "G_2" || BdewStandardLoadProfile.G2 - "g3" || BdewStandardLoadProfile.G3 - "g-3" || BdewStandardLoadProfile.G3 - "g_3" || BdewStandardLoadProfile.G3 - "G3" || BdewStandardLoadProfile.G3 - "G-3" || BdewStandardLoadProfile.G3 - "G_3" || BdewStandardLoadProfile.G3 - "g4" || BdewStandardLoadProfile.G4 - "g-4" || BdewStandardLoadProfile.G4 - "g_4" || BdewStandardLoadProfile.G4 - "G4" || BdewStandardLoadProfile.G4 - "G-4" || BdewStandardLoadProfile.G4 - "G_4" || BdewStandardLoadProfile.G4 - "g5" || BdewStandardLoadProfile.G5 - "g-5" || BdewStandardLoadProfile.G5 - "g_5" || BdewStandardLoadProfile.G5 - "G5" || BdewStandardLoadProfile.G5 - "G-5" || BdewStandardLoadProfile.G5 - "G_5" || BdewStandardLoadProfile.G5 - "g6" || BdewStandardLoadProfile.G6 - "g-6" || BdewStandardLoadProfile.G6 - "g_6" || BdewStandardLoadProfile.G6 - "G6" || BdewStandardLoadProfile.G6 - "G-6" || BdewStandardLoadProfile.G6 - "G_6" || BdewStandardLoadProfile.G6 - "g25" || BdewStandardLoadProfile.G25 - "g-25" || BdewStandardLoadProfile.G25 - "g_25" || BdewStandardLoadProfile.G25 - "G25" || BdewStandardLoadProfile.G25 - "G-25" || BdewStandardLoadProfile.G25 - "G_25" || BdewStandardLoadProfile.G25 - "p25" || BdewStandardLoadProfile.P25 - "p-25" || BdewStandardLoadProfile.P25 - "p_25" || BdewStandardLoadProfile.P25 - "P25" || BdewStandardLoadProfile.P25 - "P-25" || BdewStandardLoadProfile.P25 - "P_25" || BdewStandardLoadProfile.P25 - "s25" || BdewStandardLoadProfile.S25 - "s-25" || BdewStandardLoadProfile.S25 - "s_25" || BdewStandardLoadProfile.S25 - "S25" || BdewStandardLoadProfile.S25 - "S-25" || BdewStandardLoadProfile.S25 - "S_25" || BdewStandardLoadProfile.S25 - "ep1" || NbwTemperatureDependantLoadProfile.EP1 - "ez2" || NbwTemperatureDependantLoadProfile.EZ2 - "random" || RANDOM_LOAD_PROFILE - "" || LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE - null || LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE - } - - def "Standard load profiles can be parsed correctly"() { - when: - StandardLoadProfile actual = StandardLoadProfile.parse(key) - - then: - actual == expected - - where: - key || expected - "h0" || BdewStandardLoadProfile.H0 - "h-0" || BdewStandardLoadProfile.H0 - "h_0" || BdewStandardLoadProfile.H0 - "H0" || BdewStandardLoadProfile.H0 - "H-0" || BdewStandardLoadProfile.H0 - "H_0" || BdewStandardLoadProfile.H0 - } - - def "Temperature dependent load profiles can be parsed correctly"() { - when: - TemperatureDependantLoadProfile actual = TemperatureDependantLoadProfile.parse(key) - - then: - actual == expected - - where: - key || expected - "ep1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ez2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez-2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez_2" || NbwTemperatureDependantLoadProfile.EZ2 - } - - def "BDEW load profiles can be gotten by their key"() { - when: - BdewStandardLoadProfile actual = BdewStandardLoadProfile.get(key) - - then: - actual == expected - - where: - key || expected - "h0" || BdewStandardLoadProfile.H0 - "h-0" || BdewStandardLoadProfile.H0 - "h_0" || BdewStandardLoadProfile.H0 - "l0" || BdewStandardLoadProfile.L0 - "l-0" || BdewStandardLoadProfile.L0 - "l_0" || BdewStandardLoadProfile.L0 - "g1" || BdewStandardLoadProfile.G1 - "g-1" || BdewStandardLoadProfile.G1 - "g_1" || BdewStandardLoadProfile.G1 - } - - def "Nbw temperature dependant load profiles can be parsed correctly"() { - when: - NbwTemperatureDependantLoadProfile actual = NbwTemperatureDependantLoadProfile.get(key) - - then: - actual == expected - - where: - key || expected - "ep1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ez2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez-2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez_2" || NbwTemperatureDependantLoadProfile.EZ2 - } - - def "Nbw temperature dependant load profiles can be gotten by their key"() { - when: - NbwTemperatureDependantLoadProfile actual = NbwTemperatureDependantLoadProfile.get(key) - - then: - actual == expected - - where: - key || expected - "ep1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ep_1" || NbwTemperatureDependantLoadProfile.EP1 - "ez2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez-2" || NbwTemperatureDependantLoadProfile.EZ2 - "ez_2" || NbwTemperatureDependantLoadProfile.EZ2 - } - - def "Throws an exception when encountering an unknown key"() { - when: - LoadProfile.parse("not_a_key") - - then: - def e = thrown(ParsingException) - e.message == "No predefined load profile with key 'not_a_key' found. Please provide one of the following keys: h0, h25, l0, l1, l2, l25, g0, g1, g2, g3, g4, g5, g6, g25, p25, s25, ep1, ez2, random" - } -} diff --git a/src/test/groovy/edu/ie3/datamodel/models/profile/PowerProfileKeyTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/profile/PowerProfileKeyTest.groovy new file mode 100644 index 0000000000..78984dab26 --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/models/profile/PowerProfileKeyTest.groovy @@ -0,0 +1,124 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.datamodel.models.profile + +import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE + +import spock.lang.Specification + +class PowerProfileKeyTest extends Specification { + def "Load profile keys are parsed correctly from correct input" () { + when: + PowerProfileKey actual = new PowerProfileKey(key) + + then: + actual == expected + + where: + key || expected + "h0" || BdewStandardLoadProfile.H0.key + "h-0" || BdewStandardLoadProfile.H0.key + "h_0" || BdewStandardLoadProfile.H0.key + "H0" || BdewStandardLoadProfile.H0.key + "H-0" || BdewStandardLoadProfile.H0.key + "H_0" || BdewStandardLoadProfile.H0.key + "h25" || BdewStandardLoadProfile.H25.key + "h-25" || BdewStandardLoadProfile.H25.key + "h_25" || BdewStandardLoadProfile.H25.key + "H25" || BdewStandardLoadProfile.H25.key + "H-25" || BdewStandardLoadProfile.H25.key + "H_25" || BdewStandardLoadProfile.H25.key + "l0" || BdewStandardLoadProfile.L0.key + "l-0" || BdewStandardLoadProfile.L0.key + "l_0" || BdewStandardLoadProfile.L0.key + "L0" || BdewStandardLoadProfile.L0.key + "L-0" || BdewStandardLoadProfile.L0.key + "L_0" || BdewStandardLoadProfile.L0.key + "l1" || BdewStandardLoadProfile.L1.key + "l-1" || BdewStandardLoadProfile.L1.key + "l_1" || BdewStandardLoadProfile.L1.key + "L1" || BdewStandardLoadProfile.L1.key + "L-1" || BdewStandardLoadProfile.L1.key + "L_1" || BdewStandardLoadProfile.L1.key + "l2" || BdewStandardLoadProfile.L2.key + "l-2" || BdewStandardLoadProfile.L2.key + "l_2" || BdewStandardLoadProfile.L2.key + "L2" || BdewStandardLoadProfile.L2.key + "L-2" || BdewStandardLoadProfile.L2.key + "L_2" || BdewStandardLoadProfile.L2.key + "l25" || BdewStandardLoadProfile.L25.key + "l-25" || BdewStandardLoadProfile.L25.key + "l_25" || BdewStandardLoadProfile.L25.key + "L25" || BdewStandardLoadProfile.L25.key + "L-25" || BdewStandardLoadProfile.L25.key + "L_25" || BdewStandardLoadProfile.L25.key + "g0" || BdewStandardLoadProfile.G0.key + "g-0" || BdewStandardLoadProfile.G0.key + "g_0" || BdewStandardLoadProfile.G0.key + "G0" || BdewStandardLoadProfile.G0.key + "G-0" || BdewStandardLoadProfile.G0.key + "G_0" || BdewStandardLoadProfile.G0.key + "g1" || BdewStandardLoadProfile.G1.key + "g-1" || BdewStandardLoadProfile.G1.key + "g_1" || BdewStandardLoadProfile.G1.key + "G1" || BdewStandardLoadProfile.G1.key + "G-1" || BdewStandardLoadProfile.G1.key + "G_1" || BdewStandardLoadProfile.G1.key + "g2" || BdewStandardLoadProfile.G2.key + "g-2" || BdewStandardLoadProfile.G2.key + "g_2" || BdewStandardLoadProfile.G2.key + "G2" || BdewStandardLoadProfile.G2.key + "G-2" || BdewStandardLoadProfile.G2.key + "G_2" || BdewStandardLoadProfile.G2.key + "g3" || BdewStandardLoadProfile.G3.key + "g-3" || BdewStandardLoadProfile.G3.key + "g_3" || BdewStandardLoadProfile.G3.key + "G3" || BdewStandardLoadProfile.G3.key + "G-3" || BdewStandardLoadProfile.G3.key + "G_3" || BdewStandardLoadProfile.G3.key + "g4" || BdewStandardLoadProfile.G4.key + "g-4" || BdewStandardLoadProfile.G4.key + "g_4" || BdewStandardLoadProfile.G4.key + "G4" || BdewStandardLoadProfile.G4.key + "G-4" || BdewStandardLoadProfile.G4.key + "G_4" || BdewStandardLoadProfile.G4.key + "g5" || BdewStandardLoadProfile.G5.key + "g-5" || BdewStandardLoadProfile.G5.key + "g_5" || BdewStandardLoadProfile.G5.key + "G5" || BdewStandardLoadProfile.G5.key + "G-5" || BdewStandardLoadProfile.G5.key + "G_5" || BdewStandardLoadProfile.G5.key + "g6" || BdewStandardLoadProfile.G6.key + "g-6" || BdewStandardLoadProfile.G6.key + "g_6" || BdewStandardLoadProfile.G6.key + "G6" || BdewStandardLoadProfile.G6.key + "G-6" || BdewStandardLoadProfile.G6.key + "G_6" || BdewStandardLoadProfile.G6.key + "g25" || BdewStandardLoadProfile.G25.key + "g-25" || BdewStandardLoadProfile.G25.key + "g_25" || BdewStandardLoadProfile.G25.key + "G25" || BdewStandardLoadProfile.G25.key + "G-25" || BdewStandardLoadProfile.G25.key + "G_25" || BdewStandardLoadProfile.G25.key + "p25" || BdewStandardLoadProfile.P25.key + "p-25" || BdewStandardLoadProfile.P25.key + "p_25" || BdewStandardLoadProfile.P25.key + "P25" || BdewStandardLoadProfile.P25.key + "P-25" || BdewStandardLoadProfile.P25.key + "P_25" || BdewStandardLoadProfile.P25.key + "s25" || BdewStandardLoadProfile.S25.key + "s-25" || BdewStandardLoadProfile.S25.key + "s_25" || BdewStandardLoadProfile.S25.key + "S25" || BdewStandardLoadProfile.S25.key + "S-25" || BdewStandardLoadProfile.S25.key + "S_25" || BdewStandardLoadProfile.S25.key + "ep1" || NbwTemperatureDependantLoadProfile.EP1.key + "ez2" || NbwTemperatureDependantLoadProfile.EZ2.key + "random" || RANDOM_LOAD_PROFILE.key + "" || PowerProfileKey.NO_KEY_ASSIGNED + null || PowerProfileKey.NO_KEY_ASSIGNED + } +} diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy index ffd5a19f9c..99d889f899 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy @@ -14,7 +14,6 @@ import edu.ie3.datamodel.exceptions.InvalidEntityException import edu.ie3.datamodel.models.input.system.characteristic.WecCharacteristicInput import edu.ie3.datamodel.models.input.system.type.* import edu.ie3.datamodel.models.input.system.type.chargingpoint.ChargingPointType -import edu.ie3.datamodel.models.profile.StandardLoadProfile import edu.ie3.datamodel.utils.Try import edu.ie3.test.common.SystemParticipantTestData import edu.ie3.util.quantities.interfaces.Currency @@ -325,41 +324,9 @@ class SystemParticipantValidationUtilsTest extends Specification { where: invalidLoad || expectedSize || expectedException - SystemParticipantTestData.loadInput.copy().loadprofile(null).build() || 1 || new InvalidEntityException("No load profile defined for load", invalidLoad) + SystemParticipantTestData.loadInput.copy().loadProfile(null).build() || 1 || new InvalidEntityException("No load profile key defined for load", invalidLoad) SystemParticipantTestData.loadInput.copy().sRated(Quantities.getQuantity(-25d, ACTIVE_POWER_IN)).eConsAnnual(Quantities.getQuantity(-4000, ENERGY_IN)).build() || 1 || new InvalidEntityException("The following quantities have to be zero or positive: -25 kVA, -4000 kWh", invalidLoad) SystemParticipantTestData.loadInput.copy().cosPhiRated(2).build() || 1 || new InvalidEntityException("Rated power factor of LoadInput must be between 0 and 1", invalidLoad) - SystemParticipantTestData.loadInput.copy().loadprofile(createInvalidStandardLoadProfile("h1")).build() || 1 || new InvalidEntityException("Load profile must contain at least one valid entry: h0, g[0-6], l[0-2], ep1, ez2, random, or LoadProfile#NO_LOAD_PROFILE.", invalidLoad) - SystemParticipantTestData.loadInput.copy().loadprofile(createInvalidStandardLoadProfile("g7")).build() || 1 || new InvalidEntityException("Load profile must contain at least one valid entry: h0, g[0-6], l[0-2], ep1, ez2, random, or LoadProfile#NO_LOAD_PROFILE.", invalidLoad) - SystemParticipantTestData.loadInput.copy().loadprofile(createInvalidStandardLoadProfile("l3")).build() || 1 || new InvalidEntityException("Load profile must contain at least one valid entry: h0, g[0-6], l[0-2], ep1, ez2, random, or LoadProfile#NO_LOAD_PROFILE.", invalidLoad) - SystemParticipantTestData.loadInput.copy().loadprofile(createInvalidStandardLoadProfile("invalid")).build() || 1 || new InvalidEntityException("Load profile must contain at least one valid entry: h0, g[0-6], l[0-2], ep1, ez2, random, or LoadProfile#NO_LOAD_PROFILE.", invalidLoad) - } - - // Helper method to create invalid standard load profiles for testing - private static StandardLoadProfile createInvalidStandardLoadProfile(String profileName) { - return new StandardLoadProfile() { - @Override - String getKey() { - return profileName - } - - @Override - String toString() { - return profileName - } - - @Override - boolean equals(Object obj) { - if (obj instanceof String) { - return obj == "Simona" - } - return false - } - - @Override - int hashCode() { - return profileName.hashCode() - } - } } // PV diff --git a/src/test/groovy/edu/ie3/resources/load/BdewLoadProfileTest.groovy b/src/test/groovy/edu/ie3/resources/load/BdewLoadProfileTest.groovy index d4671a1052..054f125dc2 100644 --- a/src/test/groovy/edu/ie3/resources/load/BdewLoadProfileTest.groovy +++ b/src/test/groovy/edu/ie3/resources/load/BdewLoadProfileTest.groovy @@ -606,7 +606,7 @@ class BdewLoadProfileTest extends Specification { // helper methods private List read(BdewStandardLoadProfile profile) { - source.getSourceData(Path.of("lpts_"+profile.key)).map { it -> factory.buildModel(new LoadProfileData<>(it, BdewLoadValues)).value }.toList() + source.getSourceData(Path.of("lpts_"+profile.key.value)).map { it -> factory.buildModel(new LoadProfileData<>(it, BdewLoadValues)).value }.toList() } private static double sumValues(List values, Function extractor) { diff --git a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy index f3d87989de..72d361832c 100644 --- a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy +++ b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy @@ -91,7 +91,7 @@ class SampleJointGrid extends SystemParticipantTestData { participantNode, cosPhiFixed, emInput, - standardLoadProfile, + powerProfileKey, eConsAnnual, sRated, cosPhiRated) @@ -105,7 +105,7 @@ class SampleJointGrid extends SystemParticipantTestData { participantNode, cosPhiFixed, emInput, - standardLoadProfile, + powerProfileKey, eConsAnnual, sRated, cosPhiRated) diff --git a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy index 7611b78bcb..4c9c6db037 100644 --- a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy @@ -24,6 +24,7 @@ import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile +import edu.ie3.datamodel.models.profile.PowerProfileKey import edu.ie3.datamodel.models.profile.StandardLoadProfile import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.interfaces.* @@ -258,7 +259,7 @@ class SystemParticipantTestData { // Load protected static final ComparableQuantity eConsAnnual = Quantities.getQuantity(4000, ENERGY_IN) - protected static final StandardLoadProfile standardLoadProfile = BdewStandardLoadProfile.H0 + protected static final PowerProfileKey powerProfileKey = BdewStandardLoadProfile.H0.key public static final LoadInput loadInput = new LoadInput( UUID.fromString("eaf77f7e-9001-479f-94ca-7fb657766f5f"), "test_loadInput", @@ -267,7 +268,7 @@ class SystemParticipantTestData { participantNode, cosPhiFixed, emInput, - standardLoadProfile, + powerProfileKey, eConsAnnual, sRated, cosPhiRated diff --git a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy index eb25d08fa1..2831a828cc 100644 --- a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy @@ -401,7 +401,7 @@ trait TimeSeriesTestData { ] as Set BdewLoadProfileTimeSeries loadProfileTimeSeries = new BdewLoadProfileTimeSeries( - BdewStandardLoadProfile.G2, + BdewStandardLoadProfile.G2.key, [ new LoadProfileEntry<>( new BdewLoadValues(BdewLoadValues.BdewScheme.BDEW1999, From d4cb327dccf0292bfbfb821fa6e8b660328eef80 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 6 Feb 2026 14:13:52 +0100 Subject: [PATCH 2/3] Including reviewer's comments. --- .../io/factory/timeseries/BdewLoadProfileFactory.java | 2 +- .../io/factory/timeseries/LoadProfileFactory.java | 11 ++++------- .../ie3/datamodel/models/profile/PowerProfileKey.java | 4 ---- .../sql/SqlTimeSeriesMetaInformationSourceIT.groovy | 9 ++++++--- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java index 1c730489a8..9b381601c2 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/BdewLoadProfileFactory.java @@ -79,7 +79,7 @@ public ComparableQuantity calculateMaxPower( PowerProfileKey powerProfileKey, Set> entries) { Function valueExtractor; - if (powerProfileKey.equalsAny(H25, G25, P25, S25)) { + if (powerProfileKey.equalsAny(H0, H25, P25, S25)) { // maximum dynamization factor is on day 366 (leap year) or day 365 (regular year). // The difference between day 365 and day 366 is negligible, thus pick 366 valueExtractor = v -> BdewLoadValues.dynamization(v.getMaxValue(true), 366); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java index 3fe8048337..15df6c6dbc 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java @@ -10,12 +10,10 @@ import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries; import edu.ie3.datamodel.models.value.load.LoadValues; -import edu.ie3.util.quantities.PowerSystemUnits; import java.util.Set; import javax.measure.quantity.Energy; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; -import tech.units.indriya.quantity.Quantities; /** * Base factory for all {@link LoadProfileTimeSeries}. @@ -26,7 +24,7 @@ public abstract class LoadProfileFactory extends Factory, LoadProfileEntry> { protected static final String QUARTER_HOUR = "quarterHour"; - public LoadProfileFactory(Class valueClass) { + protected LoadProfileFactory(Class valueClass) { super(valueClass); } @@ -54,8 +52,7 @@ public String getTimeFieldString() { return QUARTER_HOUR; } - /** Returns the load profile energy scaling. The default value is 1000 kWh */ - public ComparableQuantity getLoadProfileEnergyScaling(PowerProfileKey powerProfileKey) { - return Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR); - } + /** Returns the load profile energy scaling. */ + public abstract ComparableQuantity getLoadProfileEnergyScaling( + PowerProfileKey powerProfileKey); } diff --git a/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java index a753b0adae..501fe22bc2 100644 --- a/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java +++ b/src/main/java/edu/ie3/datamodel/models/profile/PowerProfileKey.java @@ -37,10 +37,6 @@ public boolean equalsAny(PowerProfile... others) { return Arrays.stream(others).anyMatch(this::equals); } - private boolean equals(String other) { - return value.equalsIgnoreCase(toUniformKey(other)); - } - @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSourceIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSourceIT.groovy index 4f26fa36c7..1a8ffe2a31 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSourceIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMetaInformationSourceIT.groovy @@ -5,6 +5,9 @@ */ package edu.ie3.datamodel.io.source.sql +import static edu.ie3.datamodel.models.profile.BdewStandardLoadProfile.G2 +import static edu.ie3.datamodel.models.profile.BdewStandardLoadProfile.G3 + import edu.ie3.datamodel.io.connectors.SqlConnector import edu.ie3.datamodel.io.naming.DatabaseNamingStrategy import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme @@ -111,7 +114,7 @@ class SqlTimeSeriesMetaInformationSourceIT extends Specification implements Test then: result.size() == 2 - result.keySet() == ["g2", "g3"] as Set + result.keySet() == [G2.key, G3.key] as Set } def "The SQL time series meta information source returns correct meta information for a given load profile"() { @@ -123,9 +126,9 @@ class SqlTimeSeriesMetaInformationSourceIT extends Specification implements Test where: profile || expected - BdewStandardLoadProfile.G2 || true + G2 || true BdewStandardLoadProfile.G3 || true - BdewStandardLoadProfile.L0 ||false + BdewStandardLoadProfile.L0 || false } def "The SQL time series meta information source returns an empty optional for an unknown load profile"() { From fb0faf372fe2b12c960397842d47ea94c0ef66e7 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 6 Feb 2026 14:59:49 +0100 Subject: [PATCH 3/3] Updating uml diagram in docs. --- docs/uml/main/TimeSeriesDatamodelConcept.puml | 222 ++++++++++-------- .../repetitive/BdewLoadProfileTimeSeries.java | 7 +- 2 files changed, 126 insertions(+), 103 deletions(-) diff --git a/docs/uml/main/TimeSeriesDatamodelConcept.puml b/docs/uml/main/TimeSeriesDatamodelConcept.puml index 0acc0cf5f7..016f9570a7 100644 --- a/docs/uml/main/TimeSeriesDatamodelConcept.puml +++ b/docs/uml/main/TimeSeriesDatamodelConcept.puml @@ -22,90 +22,36 @@ package models { childNote .. input childNote .. voltagelevels - interface LoadProfile { - + getKey: String - + {static} parse(String): LoadProfile - + {static} getAllProfiles: LoadProfile[] - + {static} getProfile(T[], String): T - + enum DefaultLoadProfiles - + enum RandomLoadProfile + interface PowerProfileKey { + - value: String + - noKeyAssigned: boolean } - DefaultLoadProfiles --|> LoadProfile - RandomLoadProfile --|> LoadProfile + interface PowerProfile { + + getKey(): PowerProfileKey + } + PowerProfile *-- PowerProfileKey - interface StandardLoadProfile { - + {static} parse(String): StandardLoadProfile + interface LoadProfile { + + enum RandomLoadProfile } + LoadProfile ..|> PowerProfile + + interface StandardLoadProfile {} StandardLoadProfile ..|> LoadProfile + interface TemperatureDependantLoadProfile {} + TemperatureDependantLoadProfile ..|> LoadProfile + enum BdewLoadProfile { - - key: String - + {static} get(String): BdewLoadProfile + - key: PowerProfileKey } BdewLoadProfile ..|> StandardLoadProfile - package value { - interface Value - - class EnergyPriceValue { - - price: ComparableQuantity [€/MWh] - } - EnergyPriceValue ..|> Value - - class HeatDemandValue { - - heatDemand : ComparableQuantity [kW] - } - HeatDemandValue ..|> Value - - class PValue { - - p: ComparableQuantity [kW] - } - PValue ..|> Value - - class HeatAndPValue { - - heatDemand: ComparableQuantity [kW] - } - HeatAndPValue --|> PValue - - class SValue { - - q: ComparableQuantity [kVAr] - } - SValue --|> PValue - - class HeatAndSValue { - - heatDemand: ComparableQuantity [kW] - } - HeatAndSValue --|> SValue - - class SolarIrradianceValue { - - directIrradiance: ComparableQuantity [W/m²] - - diffuseIrradiance: ComparableQuantity [W/m²] - } - SolarIrradianceValue ..|> Value - - class TemperatureValue { - - temperature: ComparableQuantity [°C] - } - TemperatureValue ..|> Value - - class WindValue { - - direction: ComparableQuantity [°] - - velocity: ComparableQuantity [m/s] - } - WindValue ..|> Value - - class WeatherValue { - - coordinate: Point - - solarIrradiance: SolarIrradianceValue - - temperature: TemperatureValue - - wind: WindValue - } - WeatherValue ..|> Value - WeatherValue *-- SolarIrradianceValue - WeatherValue *-- TemperatureValue - WeatherValue *-- WindValue + enum NbwTemperatureDependantLoadProfile { + - key: PowerProfileKey } + NbwTemperatureDependantLoadProfile ..|> TemperatureDependantLoadProfile package timeseries { abstract class TimeSeries, V extends Value> { @@ -131,22 +77,21 @@ package models { } RepetitiveTimeSeries --|> TimeSeries - abstract class LoadProfileTimeSeries { - - loadProfile: StandardLoadProfile - - valueMapping: Map> - + getLoadProfile(): LoadProfile - # fromTime(ZonedDateTime): Key + abstract class LoadProfileTimeSeries { + - powerProfileKey: PowerProfileKey + - valueMapping: Map + + maxPower(): Optional> + + loadProfileScaling(): Optional> + + supplyValue(ZonedDateTime): Supplier> } LoadProfileTimeSeries --|> RepetitiveTimeSeries - LoadProfileTimeSeries *-- LoadProfile + LoadProfileTimeSeries *-- PowerProfileKey class BDEWLoadProfileTimeSeries {} BDEWLoadProfileTimeSeries --|> LoadProfileTimeSeries - BDEWLoadProfileTimeSeries *-- BdewLoadProfileEntry class RandomLoadProfileTimeSeries {} RandomLoadProfileTimeSeries --|> LoadProfileTimeSeries - RandomLoadProfileTimeSeries *-- RandomLoadProfileEntry abstract class TimeSeriesEntry { # value: V @@ -160,25 +105,108 @@ package models { TimeBasedValue --|> TimeSeriesEntry TimeBasedValue ..|> Comparable: <>: - class LoadProfileEntry { - - dayOfWeek: DayOfWeek - - quarterHourOfDay: int - + getDayOfWeek(): DayOfWeek - + getQuarterHourOfDay(): Integer + class LoadProfileEntry { + - quarterHour: int } LoadProfileEntry --|> TimeSeriesEntry: <>:PValue - - class BdewLoadProfileEntry { - - season: Season - + getSeason(): Season - } - BdewLoadProfileEntry --|> LoadProfileEntry - - class RandomLoadProfileEntry { - - gev: GeneralizedExtremeValueDistribution - } - RandomLoadProfileEntry --|> LoadProfileEntry } + + package value { + interface Value + + class EnergyPriceValue { + - price: ComparableQuantity [€/MWh] + } + EnergyPriceValue ..|> Value + + class HeatDemandValue { + - heatDemand : ComparableQuantity [kW] + } + HeatDemandValue ..|> Value + + class PValue { + - p: ComparableQuantity [kW] + } + PValue ..|> Value + + class HeatAndPValue { + - heatDemand: ComparableQuantity [kW] + } + HeatAndPValue --|> PValue + + class SValue { + - q: ComparableQuantity [kVAr] + } + SValue --|> PValue + + class HeatAndSValue { + - heatDemand: ComparableQuantity [kW] + } + HeatAndSValue --|> SValue + + class SolarIrradianceValue { + - directIrradiance: ComparableQuantity [W/m²] + - diffuseIrradiance: ComparableQuantity [W/m²] + } + SolarIrradianceValue ..|> Value + + class TemperatureValue { + - temperature: ComparableQuantity [°C] + } + TemperatureValue ..|> Value + + class WindValue { + - direction: ComparableQuantity [°] + - velocity: ComparableQuantity [m/s] + } + WindValue ..|> Value + + class WeatherValue { + - coordinate: Point + - solarIrradiance: SolarIrradianceValue + - temperature: TemperatureValue + - wind: WindValue + } + WeatherValue ..|> Value + WeatherValue *-- SolarIrradianceValue + WeatherValue *-- TemperatureValue + WeatherValue *-- WindValue + + interface LoadValues { + + getValue(ZonedDateTime, PowerProfileKey): PValue + + getScheme(): Optional + + + interface Scheme {} + } + LoadValues ..|> Value + + class BdewLoadValues { + - scheme: BdewScheme + - values: Map + + getPower(ZonedDateTime): double + + get(BdewKey): double + + getMaxValue(boolean): double + + {static} dynamization(double, int): double + + interface BdewKey + + enum BdewSeason + + enum BdewScheme + + class BdewMap + } + BdewLoadValues --|> LoadValues + + class RandomLoadValues { + - kSa: double + - kSu: double + - kWd: double + - mySa: double + - mySu: double + - myWd: double + - sigmaSa: double + - sigmaSu: double + - sigmaWd: double + } + RandomLoadValues --|> LoadValues + } } @enduml \ No newline at end of file diff --git a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java index 0da24a8c0d..87c5eb5f3d 100644 --- a/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java +++ b/src/main/java/edu/ie3/datamodel/models/timeseries/repetitive/BdewLoadProfileTimeSeries.java @@ -41,11 +41,6 @@ public int hashCode() { @Override public String toString() { - return "BDEWLoadProfileTimeSeries{" - + "loadProfileKey=" - + getPowerProfileKey().getValue() - + ", valueMapping=" - + getValueMapping() - + '}'; + return "BDEW" + super.toString(); } }