diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0c6c590e8..2b724d870 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Enhance `TimeSeriesSource` with method to retrieve all time keys after a given key [#543](https://github.com/ie3-institute/PowerSystemDataModel/issues/543)
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
+- Adding timeseries for voltage values [#1128](https://github.com/ie3-institute/PowerSystemDataModel/issues/1128)
### Fixed
diff --git a/docs/readthedocs/io/csvfiles.md b/docs/readthedocs/io/csvfiles.md
index afeb737d8..2cb522fa6 100644
--- a/docs/readthedocs/io/csvfiles.md
+++ b/docs/readthedocs/io/csvfiles.md
@@ -144,6 +144,9 @@ The following keys are supported until now:
* - pqh
- Active, reactive and heat power
Permissible head line: ``time,p,q,h``
+ * - v
+ - Voltage mangnitude in pu and angle in °
+ Permissible head line: ``time,vMag,vAng``
* - weather
- Weather information
Permissible head line: ``time,coordinate,direct_irradiation,diffuse_irradiation,temperature,wind_velocity,wind_direction``
diff --git a/docs/readthedocs/models/input/additionaldata/timeseries.md b/docs/readthedocs/models/input/additionaldata/timeseries.md
index a082ba2fb..c243c9430 100644
--- a/docs/readthedocs/models/input/additionaldata/timeseries.md
+++ b/docs/readthedocs/models/input/additionaldata/timeseries.md
@@ -32,10 +32,12 @@ The following different values are available:
- Electrical active and reactive power
* - `HeatAndPValue`
- - Combination of thermal power (e.g. in kW)
and electrical active power (e.g. in kW)
+ - | Combination of thermal power (e.g. in kW)
+ | and electrical active power (e.g. in kW)
* - `HeatAndSValue`
- - Combination of thermal power (e.g. in kW)
and electrical active and reactive power (e.g. in kW and kVAr)
+ - | Combination of thermal power (e.g. in kW)
+ | and electrical active and reactive power (e.g. in kW and kVAr)
* - `EnergyPriceValue`
- Wholesale market price (e.g. in € / MWh)
@@ -48,7 +50,10 @@ The following different values are available:
* - `WindValue`
- Combination of wind direction and wind velocity
-
+
+ * - `VoltageValue`
+ - Combination of voltage magnitude in pu and angle in °
+
* - `WeatherValue`
- Combination of irradiance, temperature and wind information
diff --git a/src/main/java/edu/ie3/datamodel/exceptions/EntityProcessorException.java b/src/main/java/edu/ie3/datamodel/exceptions/EntityProcessorException.java
index 37736b231..749b190d8 100644
--- a/src/main/java/edu/ie3/datamodel/exceptions/EntityProcessorException.java
+++ b/src/main/java/edu/ie3/datamodel/exceptions/EntityProcessorException.java
@@ -6,7 +6,7 @@
package edu.ie3.datamodel.exceptions;
/**
- * Is thrown, when an something went wrong during entity field mapping creation in a {@link
+ * Is thrown, when something went wrong during entity field mapping creation in a {@link
* edu.ie3.datamodel.io.processor.EntityProcessor}
*/
public class EntityProcessorException extends Exception {
diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java
index ab128d1e6..ee8dd059d 100644
--- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java
+++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java
@@ -13,7 +13,10 @@
import edu.ie3.datamodel.models.value.*;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
public class TimeBasedSimpleValueFactory
extends TimeBasedValueFactory, V> {
@@ -25,6 +28,10 @@ public class TimeBasedSimpleValueFactory
private static final String REACTIVE_POWER = "q";
private static final String HEAT_DEMAND = "heatDemand";
+ /* voltage */
+ private static final String VMAG = "vMag";
+ private static final String VANG = "VAng";
+
public TimeBasedSimpleValueFactory(Class extends V> valueClasses) {
super(valueClasses);
}
@@ -64,6 +71,17 @@ protected TimeBasedValue buildModel(SimpleTimeBasedValueData data) {
data.getQuantity(REACTIVE_POWER, REACTIVE_POWER_IN));
} else if (PValue.class.isAssignableFrom(data.getTargetClass())) {
value = (V) new PValue(data.getQuantity(ACTIVE_POWER, ACTIVE_POWER_IN));
+ } else if (VoltageValue.class.isAssignableFrom(data.getTargetClass())) {
+
+ try {
+ value =
+ (V)
+ new VoltageValue(
+ data.getQuantity(VMAG, VOLTAGE_MAGNITUDE),
+ data.getQuantity(VANG, VOLTAGE_ANGLE));
+ } catch (FactoryException e) {
+ value = (V) new VoltageValue(data.getQuantity(VMAG, VOLTAGE_MAGNITUDE));
+ }
} else {
throw new FactoryException(
"The given factory cannot handle target class '" + data.getTargetClass() + "'.");
diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeSeriesMappingFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeSeriesMappingFactory.java
index 2009435cc..b39a1fdc5 100644
--- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeSeriesMappingFactory.java
+++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeSeriesMappingFactory.java
@@ -8,16 +8,13 @@
import edu.ie3.datamodel.io.factory.EntityData;
import edu.ie3.datamodel.io.factory.EntityFactory;
import edu.ie3.datamodel.io.source.TimeSeriesMappingSource;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
public class TimeSeriesMappingFactory
extends EntityFactory {
- private static final String PARTICIPANT = "participant";
+ private static final String ENTITY = "entity";
private static final String TIME_SERIES = "timeSeries";
public TimeSeriesMappingFactory() {
@@ -26,14 +23,13 @@ public TimeSeriesMappingFactory() {
@Override
protected List> getFields(Class> entityClass) {
- return Collections.singletonList(
- Stream.of(PARTICIPANT, TIME_SERIES).collect(Collectors.toSet()));
+ return List.of(newSet(ENTITY, TIME_SERIES));
}
@Override
protected TimeSeriesMappingSource.MappingEntry buildModel(EntityData data) {
- UUID participant = data.getUUID(PARTICIPANT);
+ UUID entity = data.getUUID(ENTITY);
UUID timeSeries = data.getUUID(TIME_SERIES);
- return new TimeSeriesMappingSource.MappingEntry(participant, timeSeries);
+ return new TimeSeriesMappingSource.MappingEntry(entity, timeSeries);
}
}
diff --git a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/ColumnScheme.java b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/ColumnScheme.java
index 44359e34b..6ea64b458 100644
--- a/src/main/java/edu/ie3/datamodel/io/naming/timeseries/ColumnScheme.java
+++ b/src/main/java/edu/ie3/datamodel/io/naming/timeseries/ColumnScheme.java
@@ -19,7 +19,8 @@ public enum ColumnScheme {
HEAT_DEMAND("h", HeatDemandValue.class),
ACTIVE_POWER_AND_HEAT_DEMAND("ph", HeatAndPValue.class),
APPARENT_POWER_AND_HEAT_DEMAND("pqh", HeatAndSValue.class),
- WEATHER("weather", WeatherValue.class);
+ WEATHER("weather", WeatherValue.class),
+ VOLTAGE("v", VoltageValue.class);
private final String scheme;
private final Class extends Value> valueClass;
@@ -57,6 +58,7 @@ public static Optional parse(Class valueClass
if (PValue.class.isAssignableFrom(valueClass)) return Optional.of(ACTIVE_POWER);
if (HeatDemandValue.class.isAssignableFrom(valueClass)) return Optional.of(HEAT_DEMAND);
if (WeatherValue.class.isAssignableFrom(valueClass)) return Optional.of(WEATHER);
+ if (VoltageValue.class.isAssignableFrom(valueClass)) return Optional.of(VOLTAGE);
return Optional.empty();
}
}
diff --git a/src/main/java/edu/ie3/datamodel/io/processor/EntityProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/EntityProcessor.java
index d756c00cf..ac7380793 100644
--- a/src/main/java/edu/ie3/datamodel/io/processor/EntityProcessor.java
+++ b/src/main/java/edu/ie3/datamodel/io/processor/EntityProcessor.java
@@ -55,7 +55,7 @@ protected EntityProcessor(Class extends T> registeredClass) throws EntityProce
* during processing
*/
public LinkedHashMap handleEntity(T entity) throws EntityProcessorException {
- if (!registeredClass.equals(entity.getClass()))
+ if (!registeredClass.isAssignableFrom(entity.getClass()))
throw new EntityProcessorException(
"Cannot process "
+ entity.getClass().getSimpleName()
diff --git a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java
index 75a1802c6..da5e7b9fc 100644
--- a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java
+++ b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java
@@ -11,7 +11,6 @@
import edu.ie3.datamodel.io.factory.EntityData;
import edu.ie3.datamodel.io.factory.timeseries.TimeSeriesMappingFactory;
import edu.ie3.datamodel.models.input.InputEntity;
-import edu.ie3.datamodel.models.input.system.SystemParticipantInput;
import edu.ie3.datamodel.models.timeseries.TimeSeries;
import edu.ie3.datamodel.utils.Try;
import edu.ie3.datamodel.utils.Try.*;
@@ -47,7 +46,7 @@ public Map getMapping() throws SourceException {
.filter(Try::isSuccess)
.map(t -> (Success) t)
.map(Success::get)
- .collect(Collectors.toMap(MappingEntry::participant, MappingEntry::timeSeries));
+ .collect(Collectors.toMap(MappingEntry::getEntity, MappingEntry::getTimeSeries));
}
/**
@@ -80,12 +79,19 @@ private Try createMappingEntry(
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- /** Class to represent one entry within the participant to time series mapping */
- public record MappingEntry(UUID participant, UUID timeSeries) implements InputEntity {
+ /** Class to represent one entry within the entity to time series mapping */
+ public static class MappingEntry implements InputEntity {
+ private final UUID entity;
+ private final UUID timeSeries;
- /** Returns the {@link UUID} of the {@link SystemParticipantInput}. */
- public UUID getParticipant() {
- return participant;
+ public MappingEntry(UUID entity, UUID timeSeries) {
+ this.entity = entity;
+ this.timeSeries = timeSeries;
+ }
+
+ /** Returns the {@link UUID} of the {@link edu.ie3.datamodel.models.UniqueEntity}. */
+ public UUID getEntity() {
+ return entity;
}
/** Returns the {@link UUID} of the {@link TimeSeries}. */
@@ -97,17 +103,17 @@ public UUID getTimeSeries() {
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MappingEntry that)) return false;
- return participant.equals(that.participant) && timeSeries.equals(that.timeSeries);
+ return entity.equals(that.entity) && timeSeries.equals(that.timeSeries);
}
@Override
public int hashCode() {
- return Objects.hash(participant, timeSeries);
+ return Objects.hash(entity, timeSeries);
}
@Override
public String toString() {
- return "MappingEntry{" + "participant=" + participant + ", timeSeries=" + timeSeries + '}';
+ return "MappingEntry{" + "entity=" + entity + ", timeSeries=" + timeSeries + '}';
}
}
}
diff --git a/src/main/java/edu/ie3/datamodel/models/value/VoltageValue.java b/src/main/java/edu/ie3/datamodel/models/value/VoltageValue.java
new file mode 100644
index 000000000..3a77055e9
--- /dev/null
+++ b/src/main/java/edu/ie3/datamodel/models/value/VoltageValue.java
@@ -0,0 +1,89 @@
+/*
+ * © 2024. TU Dortmund University,
+ * Institute of Energy Systems, Energy Efficiency and Energy Economics,
+ * Research group Distribution grid planning and operation
+*/
+package edu.ie3.datamodel.models.value;
+
+import static edu.ie3.datamodel.models.StandardUnits.VOLTAGE_ANGLE;
+import static edu.ie3.util.quantities.PowerSystemUnits.DEGREE_GEOM;
+import static edu.ie3.util.quantities.PowerSystemUnits.PU;
+import static java.lang.Math.*;
+
+import java.util.Objects;
+import java.util.Optional;
+import javax.measure.quantity.Angle;
+import javax.measure.quantity.Dimensionless;
+import tech.units.indriya.ComparableQuantity;
+import tech.units.indriya.quantity.Quantities;
+
+/** Describes a voltage value as a pair of magnitude and angle */
+public class VoltageValue implements Value {
+
+ /** Magnitude of the voltage in p.u. */
+ private final ComparableQuantity magnitude;
+ /** Angle of the voltage in degree */
+ private final ComparableQuantity angle;
+
+ /**
+ * @param magnitude of the voltage in p.u.
+ * @param angle of the voltage in degree
+ */
+ public VoltageValue(
+ ComparableQuantity magnitude, ComparableQuantity angle) {
+ this.magnitude = magnitude;
+ this.angle = angle;
+ }
+
+ /**
+ * This constructor will set the angle to 0°
+ *
+ * @param magnitude of the voltage in p.u.
+ */
+ public VoltageValue(ComparableQuantity magnitude) {
+ this.magnitude = magnitude;
+ this.angle = Quantities.getQuantity(0.0, VOLTAGE_ANGLE);
+ }
+
+ public Optional> getMagnitude() {
+ return Optional.ofNullable(magnitude);
+ }
+
+ public Optional> getAngle() {
+ return Optional.ofNullable(angle);
+ }
+
+ public Optional> getRealPart() {
+ double mag = magnitude.to(PU).getValue().doubleValue();
+ double ang = angle.to(DEGREE_GEOM).getValue().doubleValue();
+
+ double eInPu = mag * cos(toRadians(ang));
+ return Optional.of(Quantities.getQuantity(eInPu, PU));
+ }
+
+ public Optional> getImagPart() {
+ double mag = magnitude.to(PU).getValue().doubleValue();
+ double ang = angle.to(DEGREE_GEOM).getValue().doubleValue();
+
+ double eInPu = mag * sin(toRadians(ang));
+ return Optional.of(Quantities.getQuantity(eInPu, PU));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ VoltageValue that = (VoltageValue) o;
+ return Objects.equals(magnitude, that.magnitude) && Objects.equals(angle, that.angle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(magnitude, angle);
+ }
+
+ @Override
+ public String toString() {
+ return "VoltageValue{" + "magnitude=" + magnitude + ", angle=" + angle + '}';
+ }
+}
diff --git a/src/main/java/edu/ie3/datamodel/utils/TimeSeriesUtils.java b/src/main/java/edu/ie3/datamodel/utils/TimeSeriesUtils.java
index d6ce28049..16fdcb24f 100644
--- a/src/main/java/edu/ie3/datamodel/utils/TimeSeriesUtils.java
+++ b/src/main/java/edu/ie3/datamodel/utils/TimeSeriesUtils.java
@@ -25,7 +25,8 @@ public class TimeSeriesUtils {
ENERGY_PRICE,
APPARENT_POWER_AND_HEAT_DEMAND,
ACTIVE_POWER_AND_HEAT_DEMAND,
- HEAT_DEMAND);
+ HEAT_DEMAND,
+ VOLTAGE);
/** Private Constructor as this class is not meant to be instantiated */
private TimeSeriesUtils() {
diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java
index 86be3c060..a1576dfaa 100644
--- a/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java
+++ b/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java
@@ -33,7 +33,7 @@ public class UniquenessValidationUtils extends ValidationUtils {
protected static final FieldSetSupplier congestionResultFieldSupplier =
entity -> Set.of(entity.getTime(), entity.getSubgrid());
protected static final FieldSetSupplier mappingFieldSupplier =
- entity -> Set.of(entity.participant());
+ entity -> Set.of(entity.getEntity());
protected static final FieldSetSupplier idCoordinateSupplier =
entity -> Set.of(entity.id(), entity.point());
protected static final FieldSetSupplier> weatherValueFieldSupplier =
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 24b1a8198..de99a0067 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
@@ -630,7 +630,7 @@ class InputEntityProcessorTest extends Specification {
def validResult = new TimeSeriesMappingSource.MappingEntry(UUID.fromString("7eb7b296-f4c4-4020-acf3-e865453b5dbd"), UUID.fromString("bc581c6c-3044-48a1-aea1-5b2cb1370356"))
Map expectedResults = [
- "participant": "7eb7b296-f4c4-4020-acf3-e865453b5dbd",
+ "entity": "7eb7b296-f4c4-4020-acf3-e865453b5dbd",
"timeSeries": "bc581c6c-3044-48a1-aea1-5b2cb1370356"
]
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSourceIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSourceIT.groovy
index 91ff12295..2abcc918c 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSourceIT.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSourceIT.groovy
@@ -23,7 +23,8 @@ class CsvTimeSeriesMappingSourceIT extends Specification implements CsvTestDataM
def expectedMapping = [
(UUID.fromString("b86e95b0-e579-4a80-a534-37c7a470a409")) : UUID.fromString("9185b8c1-86ba-4a16-8dea-5ac898e8caa5"),
(UUID.fromString("c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8")) : UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26"),
- (UUID.fromString("90a96daa-012b-4fea-82dc-24ba7a7ab81c")) : UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26")
+ (UUID.fromString("90a96daa-012b-4fea-82dc-24ba7a7ab81c")) : UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26"),
+ (UUID.fromString("7bed7760-c220-4fe6-88b3-47b246f6ef3f")) : UUID.fromString("eeccbe3c-a47e-448e-8eca-1f369d3c24e6")
]
when:
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMetaInformationSourceIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMetaInformationSourceIT.groovy
index 2fa70a2f6..6623e76ca 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMetaInformationSourceIT.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMetaInformationSourceIT.groovy
@@ -30,14 +30,15 @@ class CsvTimeSeriesMetaInformationSourceIT extends Specification implements CsvT
new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("9185b8c1-86ba-4a16-8dea-5ac898e8caa5"), ColumnScheme.ACTIVE_POWER, Path.of('its_p_9185b8c1-86ba-4a16-8dea-5ac898e8caa5')),
new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26"), ColumnScheme.APPARENT_POWER, Path.of('its_pq_3fbfaa97-cff4-46d4-95ba-a95665e87c26')),
new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("46be1e57-e4ed-4ef7-95f1-b2b321cb2047"), ColumnScheme.APPARENT_POWER_AND_HEAT_DEMAND, Path.of('its_pqh_46be1e57-e4ed-4ef7-95f1-b2b321cb2047')),
- new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("1061af70-1c03-46e1-b960-940b956c429f"), ColumnScheme.APPARENT_POWER, Path.of('its_pq_1061af70-1c03-46e1-b960-940b956c429f'))
+ new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("1061af70-1c03-46e1-b960-940b956c429f"), ColumnScheme.APPARENT_POWER, Path.of('its_pq_1061af70-1c03-46e1-b960-940b956c429f')),
+ new CsvIndividualTimeSeriesMetaInformation(UUID.fromString("eeccbe3c-a47e-448e-8eca-1f369d3c24e6"), ColumnScheme.VOLTAGE, Path.of("its_v_eeccbe3c-a47e-448e-8eca-1f369d3c24e6"))
)
when:
def actual = source.timeSeriesMetaInformation
then:
- actual.size() == 7
+ actual.size() == 8
actual.every {
it.key == it.value.uuid &&
expectedTimeSeries.contains(it.value)
@@ -62,6 +63,7 @@ class CsvTimeSeriesMetaInformationSourceIT extends Specification implements CsvT
"3fbfaa97-cff4-46d4-95ba-a95665e87c26" || "pq"
"46be1e57-e4ed-4ef7-95f1-b2b321cb2047" || "pqh"
"1061af70-1c03-46e1-b960-940b956c429f" || "pq"
+ "eeccbe3c-a47e-448e-8eca-1f369d3c24e6" || "v"
}
def "The CSV time series meta information source returns an empty optional for an unknown time series UUID"() {
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSourceTest.groovy
index 445ddc403..47d662b9a 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSourceTest.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSourceTest.groovy
@@ -94,5 +94,6 @@ class CsvTimeSeriesSourceTest extends Specification implements CsvTestDataMeta {
UUID.fromString("76c9d846-797c-4f07-b7ec-2245f679f5c7") | ColumnScheme.ACTIVE_POWER_AND_HEAT_DEMAND | Path.of("its_ph_76c9d846-797c-4f07-b7ec-2245f679f5c7") || 2 | HeatAndPValue
UUID.fromString("3fbfaa97-cff4-46d4-95ba-a95665e87c26") | ColumnScheme.APPARENT_POWER | Path.of("its_pq_3fbfaa97-cff4-46d4-95ba-a95665e87c26") || 2 | SValue
UUID.fromString("46be1e57-e4ed-4ef7-95f1-b2b321cb2047") | ColumnScheme.APPARENT_POWER_AND_HEAT_DEMAND | Path.of("its_pqh_46be1e57-e4ed-4ef7-95f1-b2b321cb2047") || 2 | HeatAndSValue
+ UUID.fromString("eeccbe3c-a47e-448e-8eca-1f369d3c24e6") | ColumnScheme.VOLTAGE | Path.of("its_v_eeccbe3c-a47e-448e-8eca-1f369d3c24e6") || 2 | VoltageValue
}
}
\ No newline at end of file
diff --git a/src/test/groovy/edu/ie3/datamodel/models/value/VoltageValueTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/value/VoltageValueTest.groovy
new file mode 100644
index 000000000..08b264476
--- /dev/null
+++ b/src/test/groovy/edu/ie3/datamodel/models/value/VoltageValueTest.groovy
@@ -0,0 +1,46 @@
+/*
+ * © 2024. TU Dortmund University,
+ * Institute of Energy Systems, Energy Efficiency and Energy Economics,
+ * Research group Distribution grid planning and operation
+ */
+package edu.ie3.datamodel.models.value
+
+import static edu.ie3.util.quantities.PowerSystemUnits.*
+
+import spock.lang.Specification
+import tech.units.indriya.quantity.Quantities
+
+
+class VoltageValueTest extends Specification {
+
+ def "A VoltageValue should return the real part correctly"() {
+ when:
+ def actual = value.realPart
+
+ then:
+ actual.isPresent()
+ actual.get() =~ expected
+
+ where:
+ value | expected
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(0, DEGREE_GEOM)) | Quantities.getQuantity(1, PU)
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(45, DEGREE_GEOM)) | Quantities.getQuantity(0.7071067811865476, PU)
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(90, DEGREE_GEOM)) | Quantities.getQuantity(6.123233995736766E-17, PU) // ~0pu
+ }
+
+
+ def "A VoltageValue should return the imaginary part correctly"() {
+ when:
+ def actual = value.imagPart
+
+ then:
+ actual.isPresent()
+ actual.get() =~ expected
+
+ where:
+ value | expected
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(0, DEGREE_GEOM)) | Quantities.getQuantity(0, PU)
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(45, DEGREE_GEOM)) | Quantities.getQuantity(0.7071067811865475, PU)
+ new VoltageValue(Quantities.getQuantity(1, PU), Quantities.getQuantity(90, DEGREE_GEOM)) | Quantities.getQuantity(1, PU)
+ }
+}
diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy
index d33502cb1..95b2f0472 100644
--- a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy
@@ -23,6 +23,7 @@ import edu.ie3.datamodel.models.value.SolarIrradianceValue
import edu.ie3.datamodel.models.value.TemperatureValue
import edu.ie3.datamodel.models.value.WeatherValue
import edu.ie3.datamodel.models.value.WindValue
+import edu.ie3.datamodel.utils.Try
import edu.ie3.util.geo.GeoUtils
import spock.lang.Specification
import tech.units.indriya.quantity.Quantities
@@ -183,29 +184,30 @@ class UniquenessValidationUtilsTest extends Specification {
given:
UUID participant = UUID.fromString("1f25eea2-20eb-4b6b-8f05-bdbb0e851e65")
- Set uniqueEntries = [
+ Set uniqueEntityEntries = [
new TimeSeriesMappingSource.MappingEntry(participant, UUID.randomUUID()),
new TimeSeriesMappingSource.MappingEntry(participant, UUID.randomUUID()),
]
when:
- checkMappingEntryUniqueness(uniqueEntries)
+ def entityDuplicate = Try.ofVoid(() -> checkMappingEntryUniqueness(uniqueEntityEntries), DuplicateEntitiesException)
then:
- DuplicateEntitiesException de = thrown()
- de.message == "'MappingEntry' entities with duplicated UUID key, but different field values found! " +
- "Affected primary keys: [1f25eea2-20eb-4b6b-8f05-bdbb0e851e65]"
+
+ entityDuplicate.failure
+ entityDuplicate.exception.get().message == "'MappingEntry' entities with duplicated UUID key, but different field values found! " +
+ "Affected primary keys: [1f25eea2-20eb-4b6b-8f05-bdbb0e851e65]"
}
def "Checking if time based weather values are unique"() {
given:
ZonedDateTime time = ZonedDateTime.now()
WeatherValue value = new WeatherValue(
- GeoUtils.buildPoint(50d, 7d),
- new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)),
- new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)),
- new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND))
- )
+ GeoUtils.buildPoint(50d, 7d),
+ new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)),
+ new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)),
+ new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND))
+ )
Set> uniqueValues = [
new TimeBasedValue(time, value),
@@ -223,11 +225,11 @@ class UniquenessValidationUtilsTest extends Specification {
given:
ZonedDateTime time = ZonedDateTime.now()
WeatherValue value = new WeatherValue(
- GeoUtils.buildPoint(50d, 7d),
- new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)),
- new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)),
- new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND))
- )
+ GeoUtils.buildPoint(50d, 7d),
+ new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)),
+ new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)),
+ new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND))
+ )
Set> notUniqueValues = [
new TimeBasedValue(time, value),
new TimeBasedValue(time, value)
diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/its_v_eeccbe3c-a47e-448e-8eca-1f369d3c24e6.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/its_v_eeccbe3c-a47e-448e-8eca-1f369d3c24e6.csv
new file mode 100644
index 000000000..1d776f689
--- /dev/null
+++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/its_v_eeccbe3c-a47e-448e-8eca-1f369d3c24e6.csv
@@ -0,0 +1,3 @@
+"time";"vMag";"vAng"
+2020-01-01T00:00:00Z;1.0;45.0
+2020-01-01T00:15:00Z;0.9;
\ No newline at end of file
diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/time_series_mapping.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/time_series_mapping.csv
index d0130d232..2e1897b2a 100644
--- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/time_series_mapping.csv
+++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_timeseries/time_series_mapping.csv
@@ -1,4 +1,5 @@
-"uuid";"participant";"time_series"
-"58167015-d760-4f90-8109-f2ebd94cda91";"b86e95b0-e579-4a80-a534-37c7a470a409";"9185b8c1-86ba-4a16-8dea-5ac898e8caa5"
-"9a9ebfda-dc26-4a40-b9ca-25cd42f6cc3f";"c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8";"3fbfaa97-cff4-46d4-95ba-a95665e87c26"
-"9c1c53ea-e575-41a2-a373-a8b2d3ed2c39";"90a96daa-012b-4fea-82dc-24ba7a7ab81c";"3fbfaa97-cff4-46d4-95ba-a95665e87c26"
\ No newline at end of file
+"entity";"time_series"
+"b86e95b0-e579-4a80-a534-37c7a470a409";"9185b8c1-86ba-4a16-8dea-5ac898e8caa5"
+"c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8";"3fbfaa97-cff4-46d4-95ba-a95665e87c26"
+"90a96daa-012b-4fea-82dc-24ba7a7ab81c";"3fbfaa97-cff4-46d4-95ba-a95665e87c26"
+"7bed7760-c220-4fe6-88b3-47b246f6ef3f";"eeccbe3c-a47e-448e-8eca-1f369d3c24e6"
\ No newline at end of file
diff --git a/src/test/resources/edu/ie3/datamodel/io/source/sql/_timeseries/time_series_mapping.sql b/src/test/resources/edu/ie3/datamodel/io/source/sql/_timeseries/time_series_mapping.sql
index b3921f442..260fa5224 100644
--- a/src/test/resources/edu/ie3/datamodel/io/source/sql/_timeseries/time_series_mapping.sql
+++ b/src/test/resources/edu/ie3/datamodel/io/source/sql/_timeseries/time_series_mapping.sql
@@ -1,15 +1,14 @@
CREATE TABLE public.time_series_mapping
(
- uuid uuid PRIMARY KEY,
- participant uuid,
+ entity uuid PRIMARY KEY,
time_series uuid
)
WITHOUT OIDS
TABLESPACE pg_default;
INSERT INTO
- public.time_series_mapping (uuid, participant, time_series)
+ public.time_series_mapping (entity, time_series)
VALUES
-('58167015-d760-4f90-8109-f2ebd94cda91', 'b86e95b0-e579-4a80-a534-37c7a470a409', '9185b8c1-86ba-4a16-8dea-5ac898e8caa5'),
-('9a9ebfda-dc26-4a40-b9ca-25cd42f6cc3f', 'c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8', '3fbfaa97-cff4-46d4-95ba-a95665e87c26'),
-('9c1c53ea-e575-41a2-a373-a8b2d3ed2c39', '90a96daa-012b-4fea-82dc-24ba7a7ab81c', '3fbfaa97-cff4-46d4-95ba-a95665e87c26');
+('b86e95b0-e579-4a80-a534-37c7a470a409', '9185b8c1-86ba-4a16-8dea-5ac898e8caa5'),
+('c7ebcc6c-55fc-479b-aa6b-6fa82ccac6b8', '3fbfaa97-cff4-46d4-95ba-a95665e87c26'),
+('90a96daa-012b-4fea-82dc-24ba7a7ab81c', '3fbfaa97-cff4-46d4-95ba-a95665e87c26');