Skip to content

Commit 1079cb6

Browse files
Merge pull request #1130 from ie3-institute/ms/#1128-adding-voltage-timeseries
Adding a timeseries for voltage values.
2 parents 934600c + 99312f7 commit 1079cb6

File tree

14 files changed

+200
-14
lines changed

14 files changed

+200
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
- Enhance `TimeSeriesSource` with method to retrieve all time keys after a given key [#543](https://github.com/ie3-institute/PowerSystemDataModel/issues/543)
1111
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
12+
- Adding timeseries for voltage values [#1128](https://github.com/ie3-institute/PowerSystemDataModel/issues/1128)
1213

1314
### Fixed
1415

docs/readthedocs/io/csvfiles.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,30 +122,34 @@ This is the UUID from the example above `2fcb3e53-b94a-4b96-bea4-c469e499f1a1`.
122122
The following keys are supported until now:
123123
```{list-table}
124124
:widths: auto
125+
:class: wrapping
125126
:header-rows: 1
126127
127128
* - Key
128-
- Information and supported head line
129+
- Information and supported head line.
129130
* - c
130131
- An energy price (e.g. in €/MWh; c stands for charge).
131132
Permissible head line: ``time,price``
132133
* - p
133-
- Active power
134+
- Active power.
134135
Permissible head line: ``time,p``
135136
* - pq
136-
- Active and reactive power
137+
- Active and reactive power.
137138
Permissible head line: ``time,p,q``
138139
* - h
139-
- Heat power demand
140+
- Heat power demand.
140141
Permissible head line: ``time,h``
141142
* - ph
142-
- Active and heat power
143+
- Active and heat power.
143144
Permissible head line: ``time,p,h``
144145
* - pqh
145-
- Active, reactive and heat power
146+
- Active, reactive and heat power.
146147
Permissible head line: ``time,p,q,h``
148+
* - v
149+
- Voltage mangnitude in pu and angle in °.
150+
Permissible head line: ``time,vMag,vAng``
147151
* - weather
148-
- Weather information
152+
- Weather information.
149153
Permissible head line: ``time,coordinate,direct_irradiation,diffuse_irradiation,temperature,wind_velocity,wind_direction``
150154
151155
```

docs/readthedocs/models/input/additionaldata/timeseries.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ The following different values are available:
4848
4949
* - `WindValue`
5050
- Combination of wind direction and wind velocity
51-
51+
52+
* - `VoltageValue`
53+
- Combination of voltage magnitude in p.u. and angle in °
54+
5255
* - `WeatherValue`
5356
- Combination of irradiance, temperature and wind information
5457

src/main/java/edu/ie3/datamodel/exceptions/EntityProcessorException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
package edu.ie3.datamodel.exceptions;
77

88
/**
9-
* Is thrown, when an something went wrong during entity field mapping creation in a {@link
9+
* Is thrown, when something went wrong during entity field mapping creation in a {@link
1010
* edu.ie3.datamodel.io.processor.EntityProcessor}
1111
*/
1212
public class EntityProcessorException extends Exception {

src/main/java/edu/ie3/datamodel/io/factory/FactoryData.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ public <Q extends Quantity<Q>> ComparableQuantity<Q> getQuantity(String field, U
7878
return Quantities.getQuantity(getDouble(field), unit);
7979
}
8080

81+
/**
82+
* Returns field value for given field name, or empty Optional if field does not exist.
83+
*
84+
* @param field field name
85+
* @param unit unit of Quantity
86+
* @param <Q> unit type parameter
87+
* @return field value
88+
*/
89+
public <Q extends Quantity<Q>> Optional<ComparableQuantity<Q>> getQuantityOptional(
90+
String field, Unit<Q> unit) {
91+
return Optional.ofNullable(fieldsToAttributes.get(field))
92+
.filter(str -> !str.isEmpty())
93+
.map(Double::parseDouble)
94+
.map(value -> Quantities.getQuantity(value, unit));
95+
}
96+
8197
/**
8298
* Returns int value for given field name. Throws {@link FactoryException} if field does not exist
8399
* or parsing fails.

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public class TimeBasedSimpleValueFactory<V extends Value>
2525
private static final String REACTIVE_POWER = "q";
2626
private static final String HEAT_DEMAND = "heatDemand";
2727

28+
/* voltage */
29+
private static final String VMAG = "vMag";
30+
private static final String VANG = "VAng";
31+
2832
public TimeBasedSimpleValueFactory(Class<? extends V> valueClasses) {
2933
super(valueClasses);
3034
}
@@ -35,6 +39,7 @@ public TimeBasedSimpleValueFactory(
3539
}
3640

3741
@Override
42+
@SuppressWarnings("unchecked")
3843
protected TimeBasedValue<V> buildModel(SimpleTimeBasedValueData<V> data) {
3944
ZonedDateTime time = timeUtil.toZonedDateTime(data.getField(TIME));
4045
V value;
@@ -64,6 +69,12 @@ protected TimeBasedValue<V> buildModel(SimpleTimeBasedValueData<V> data) {
6469
data.getQuantity(REACTIVE_POWER, REACTIVE_POWER_IN));
6570
} else if (PValue.class.isAssignableFrom(data.getTargetClass())) {
6671
value = (V) new PValue(data.getQuantity(ACTIVE_POWER, ACTIVE_POWER_IN));
72+
} else if (VoltageValue.class.isAssignableFrom(data.getTargetClass())) {
73+
value =
74+
(V)
75+
new VoltageValue(
76+
data.getQuantity(VMAG, VOLTAGE_MAGNITUDE),
77+
data.getQuantityOptional(VANG, VOLTAGE_ANGLE));
6778
} else {
6879
throw new FactoryException(
6980
"The given factory cannot handle target class '" + data.getTargetClass() + "'.");
@@ -88,6 +99,8 @@ protected List<Set<String>> getFields(Class<?> entityClass) {
8899
minConstructorParams.addAll(Arrays.asList(ACTIVE_POWER, REACTIVE_POWER));
89100
} else if (PValue.class.isAssignableFrom(entityClass)) {
90101
minConstructorParams.add(ACTIVE_POWER);
102+
} else if (VoltageValue.class.isAssignableFrom(entityClass)) {
103+
minConstructorParams.addAll(List.of(VMAG, VANG));
91104
} else {
92105
throw new FactoryException(
93106
"The given factory cannot handle target class '" + entityClass + "'.");

src/main/java/edu/ie3/datamodel/io/naming/timeseries/ColumnScheme.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public enum ColumnScheme {
1919
HEAT_DEMAND("h", HeatDemandValue.class),
2020
ACTIVE_POWER_AND_HEAT_DEMAND("ph", HeatAndPValue.class),
2121
APPARENT_POWER_AND_HEAT_DEMAND("pqh", HeatAndSValue.class),
22-
WEATHER("weather", WeatherValue.class);
22+
WEATHER("weather", WeatherValue.class),
23+
VOLTAGE("v", VoltageValue.class);
2324

2425
private final String scheme;
2526
private final Class<? extends Value> valueClass;
@@ -57,6 +58,7 @@ public static <V extends Value> Optional<ColumnScheme> parse(Class<V> valueClass
5758
if (PValue.class.isAssignableFrom(valueClass)) return Optional.of(ACTIVE_POWER);
5859
if (HeatDemandValue.class.isAssignableFrom(valueClass)) return Optional.of(HEAT_DEMAND);
5960
if (WeatherValue.class.isAssignableFrom(valueClass)) return Optional.of(WEATHER);
61+
if (VoltageValue.class.isAssignableFrom(valueClass)) return Optional.of(VOLTAGE);
6062
return Optional.empty();
6163
}
6264
}

src/main/java/edu/ie3/datamodel/io/processor/EntityProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected EntityProcessor(Class<? extends T> registeredClass) throws EntityProce
5555
* during processing
5656
*/
5757
public LinkedHashMap<String, String> handleEntity(T entity) throws EntityProcessorException {
58-
if (!registeredClass.equals(entity.getClass()))
58+
if (!registeredClass.isAssignableFrom(entity.getClass()))
5959
throw new EntityProcessorException(
6060
"Cannot process "
6161
+ entity.getClass().getSimpleName()
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* © 2024. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.models.value;
7+
8+
import static edu.ie3.datamodel.models.StandardUnits.VOLTAGE_ANGLE;
9+
import static edu.ie3.util.quantities.PowerSystemUnits.DEGREE_GEOM;
10+
import static edu.ie3.util.quantities.PowerSystemUnits.PU;
11+
import static java.lang.Math.*;
12+
13+
import java.util.Objects;
14+
import java.util.Optional;
15+
import javax.measure.quantity.Angle;
16+
import javax.measure.quantity.Dimensionless;
17+
import tech.units.indriya.ComparableQuantity;
18+
import tech.units.indriya.quantity.Quantities;
19+
20+
/** Describes a voltage value as a pair of magnitude and angle */
21+
public class VoltageValue implements Value {
22+
23+
/** Magnitude of the voltage in p.u. */
24+
private final ComparableQuantity<Dimensionless> magnitude;
25+
/** Angle of the voltage in degree */
26+
private final ComparableQuantity<Angle> angle;
27+
28+
/**
29+
* @param magnitude of the voltage in p.u.
30+
* @param angleOption option for the angle of this voltage in degree
31+
*/
32+
public VoltageValue(
33+
ComparableQuantity<Dimensionless> magnitude,
34+
Optional<ComparableQuantity<Angle>> angleOption) {
35+
this.magnitude = magnitude;
36+
this.angle = angleOption.orElse(Quantities.getQuantity(0.0, VOLTAGE_ANGLE));
37+
}
38+
39+
/**
40+
* @param magnitude of the voltage in p.u.
41+
* @param angle of the voltage in degree
42+
*/
43+
public VoltageValue(
44+
ComparableQuantity<Dimensionless> magnitude, ComparableQuantity<Angle> angle) {
45+
this.magnitude = magnitude;
46+
this.angle = angle;
47+
}
48+
49+
public Optional<ComparableQuantity<Dimensionless>> getMagnitude() {
50+
return Optional.ofNullable(magnitude);
51+
}
52+
53+
public Optional<ComparableQuantity<Angle>> getAngle() {
54+
return Optional.ofNullable(angle);
55+
}
56+
57+
public Optional<ComparableQuantity<Dimensionless>> getRealPart() {
58+
double mag = magnitude.to(PU).getValue().doubleValue();
59+
double ang = angle.to(DEGREE_GEOM).getValue().doubleValue();
60+
61+
double eInPu = mag * cos(toRadians(ang));
62+
return Optional.of(Quantities.getQuantity(eInPu, PU));
63+
}
64+
65+
public Optional<ComparableQuantity<Dimensionless>> getImagPart() {
66+
double mag = magnitude.to(PU).getValue().doubleValue();
67+
double ang = angle.to(DEGREE_GEOM).getValue().doubleValue();
68+
69+
double fInPu = mag * sin(toRadians(ang));
70+
return Optional.of(Quantities.getQuantity(fInPu, PU));
71+
}
72+
73+
@Override
74+
public boolean equals(Object o) {
75+
if (this == o) return true;
76+
if (o == null || getClass() != o.getClass()) return false;
77+
VoltageValue that = (VoltageValue) o;
78+
return Objects.equals(magnitude, that.magnitude) && Objects.equals(angle, that.angle);
79+
}
80+
81+
@Override
82+
public int hashCode() {
83+
return Objects.hash(magnitude, angle);
84+
}
85+
86+
@Override
87+
public String toString() {
88+
return "VoltageValue{" + "magnitude=" + magnitude + ", angle=" + angle + '}';
89+
}
90+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public class TimeSeriesUtils {
2525
ENERGY_PRICE,
2626
APPARENT_POWER_AND_HEAT_DEMAND,
2727
ACTIVE_POWER_AND_HEAT_DEMAND,
28-
HEAT_DEMAND);
28+
HEAT_DEMAND,
29+
VOLTAGE);
2930

3031
/** Private Constructor as this class is not meant to be instantiated */
3132
private TimeSeriesUtils() {

0 commit comments

Comments
 (0)