Skip to content

Commit 59e2114

Browse files
committed
Added RandomLoadProfileTimeSeries
1 parent bf62c4a commit 59e2114

File tree

14 files changed

+542
-152
lines changed

14 files changed

+542
-152
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Extend ValidationUtils for validating ThermalGrids [#1216](https://github.com/ie3-institute/PowerSystemDataModel/issues/1216)
1515
- Enhance `TimeSeriesSource` with method to retrieve the previous value before a given key [#1182](https://github.com/ie3-institute/PowerSystemDataModel/issues/1182)
1616
- Added `BdewLoadProfileTimeSeries` [#1230](https://github.com/ie3-institute/PowerSystemDataModel/issues/1230)
17+
- Added `RandomLoadProfileTimeSeries` [#1232](https://github.com/ie3-institute/PowerSystemDataModel/issues/1232)
1718

1819
### Fixed
1920
- Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221)

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ plugins {
1111
id 'jacoco' // java code coverage plugin
1212
id "org.sonarqube" version "6.0.1.5171" // sonarqube
1313
id 'net.thauvin.erik.gradle.semver' version '1.0.4' // semantic versioning
14+
id "com.github.johnrengelman.shadow" version "8.1.1" // fat jar
1415
}
1516

1617
ext {
@@ -67,6 +68,9 @@ dependencies {
6768
// Graphs
6869
implementation 'org.jgrapht:jgrapht-core:1.5.2'
6970

71+
// Statistics (for random load model)
72+
implementation 'de.lmu.ifi.dbs.elki:elki:0.7.5'
73+
7074
// testing
7175
testImplementation "org.apache.groovy:groovy:$groovyBinaryVersion"
7276

docs/uml/main/TimeSeriesDatamodelConcept.puml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package models {
3232
}
3333

3434
DefaultLoadProfiles --|> LoadProfile
35+
RandomLoadProfile --|> LoadProfile
3536

3637
interface StandardLoadProfile {
3738
+ {static} parse(String): StandardLoadProfile
@@ -130,12 +131,22 @@ package models {
130131
}
131132
RepetitiveTimeSeries --|> TimeSeries
132133

133-
class LoadProfileInput {
134-
- type: StandardLoadProfile
135-
- dayOfWeekToHourlyValues: Map<DayOfWeek, Map<Integer, PValue>>
134+
abstract class LoadProfileTimeSeries<E extends LoadProfileEntry> {
135+
- loadProfile: StandardLoadProfile
136+
- valueMapping: Map<Key, Map<Integer, E>>
137+
+ getLoadProfile(): LoadProfile
138+
# fromTime(ZonedDateTime): Key
136139
}
137-
LoadProfileInput --|> RepetitiveTimeSeries
138-
LoadProfileInput *-- StandardLoadProfile
140+
LoadProfileTimeSeries --|> RepetitiveTimeSeries
141+
LoadProfileTimeSeries *-- LoadProfile
142+
143+
class BDEWLoadProfileTimeSeries {}
144+
BDEWLoadProfileTimeSeries --|> LoadProfileTimeSeries
145+
BDEWLoadProfileTimeSeries *-- BdewLoadProfileEntry
146+
147+
class RandomLoadProfileTimeSeries {}
148+
RandomLoadProfileTimeSeries --|> LoadProfileTimeSeries
149+
RandomLoadProfileTimeSeries *-- RandomLoadProfileEntry
139150

140151
abstract class TimeSeriesEntry <V extends Value> {
141152
# value: V
@@ -152,8 +163,21 @@ package models {
152163
class LoadProfileEntry {
153164
- dayOfWeek: DayOfWeek
154165
- quarterHourOfDay: int
166+
+ getDayOfWeek(): DayOfWeek
167+
+ getQuarterHourOfDay(): Integer
155168
}
156169
LoadProfileEntry --|> TimeSeriesEntry: <<bind>>:PValue
170+
171+
class BdewLoadProfileEntry {
172+
- season: Season
173+
+ getSeason(): Season
174+
}
175+
BdewLoadProfileEntry --|> LoadProfileEntry
176+
177+
class RandomLoadProfileEntry {
178+
- gev: GeneralizedExtremeValueDistribution
179+
}
180+
RandomLoadProfileEntry --|> LoadProfileEntry
157181
}
158182
}
159183

docs/uml/main/input/InputDatamodelConcept.puml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,6 @@ package models {
142142
MeasurementUnitInput --|> AssetInput
143143
MeasurementUnitInput ..|> HasNodes
144144

145-
class RandomLoadParameter {
146-
- quarterHour: int
147-
- kWd: Double
148-
- kSa: Double
149-
- kSu: Double
150-
- myWd: Double
151-
- mySa: Double
152-
- mySu: Double
153-
- sigmaWd: Double
154-
- sigmaSa: Double
155-
- sigmaSu: Double
156-
}
157-
RandomLoadParameter --|> InputEntity
158-
159145
abstract class AssetTypeInput {
160146
- id: String
161147
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.io.factory.timeseries;
7+
8+
import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE;
9+
10+
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
11+
import edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile;
12+
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry;
13+
import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries;
14+
import edu.ie3.datamodel.models.value.load.RandomLoadValues;
15+
import edu.ie3.util.quantities.PowerSystemUnits;
16+
import java.util.List;
17+
import java.util.Optional;
18+
import java.util.Set;
19+
import javax.measure.quantity.Energy;
20+
import javax.measure.quantity.Power;
21+
import tech.units.indriya.ComparableQuantity;
22+
import tech.units.indriya.quantity.Quantities;
23+
24+
public class RandomLoadProfileFactory
25+
extends LoadProfileFactory<RandomLoadProfile, RandomLoadValues> {
26+
public static final String K_WEEKDAY = "kWd";
27+
public static final String K_SATURDAY = "kSa";
28+
public static final String K_SUNDAY = "kSu";
29+
public static final String MY_WEEKDAY = "myWd";
30+
public static final String MY_SATURDAY = "mySa";
31+
public static final String MY_SUNDAY = "mySu";
32+
public static final String SIGMA_WEEKDAY = "sigmaWd";
33+
public static final String SIGMA_SATURDAY = "sigmaSa";
34+
public static final String SIGMA_SUNDAY = "sigmaSu";
35+
36+
public RandomLoadProfileFactory() {
37+
super(RandomLoadValues.class);
38+
}
39+
40+
@Override
41+
protected LoadProfileEntry<RandomLoadValues> buildModel(LoadProfileData<RandomLoadValues> data) {
42+
int quarterHour = data.getInt(QUARTER_HOUR);
43+
44+
return new LoadProfileEntry<>(
45+
new RandomLoadValues(
46+
data.getDouble(K_SATURDAY),
47+
data.getDouble(K_SUNDAY),
48+
data.getDouble(K_WEEKDAY),
49+
data.getDouble(MY_SATURDAY),
50+
data.getDouble(MY_SUNDAY),
51+
data.getDouble(MY_WEEKDAY),
52+
data.getDouble(SIGMA_SATURDAY),
53+
data.getDouble(SIGMA_SUNDAY),
54+
data.getDouble(SIGMA_WEEKDAY)),
55+
quarterHour);
56+
}
57+
58+
@Override
59+
protected List<Set<String>> getFields(Class<?> entityClass) {
60+
return List.of(
61+
newSet(
62+
QUARTER_HOUR,
63+
K_WEEKDAY,
64+
K_SATURDAY,
65+
K_SUNDAY,
66+
MY_WEEKDAY,
67+
MY_SATURDAY,
68+
MY_SUNDAY,
69+
SIGMA_WEEKDAY,
70+
SIGMA_SATURDAY,
71+
SIGMA_SUNDAY));
72+
}
73+
74+
@Override
75+
public RandomLoadProfileTimeSeries build(
76+
LoadProfileMetaInformation metaInformation, Set<LoadProfileEntry<RandomLoadValues>> entries) {
77+
return new RandomLoadProfileTimeSeries(metaInformation.getUuid(), RANDOM_LOAD_PROFILE, entries);
78+
}
79+
80+
@Override
81+
public RandomLoadProfile parseProfile(String profile) {
82+
return RANDOM_LOAD_PROFILE;
83+
}
84+
85+
@Override
86+
public Optional<ComparableQuantity<Power>> calculateMaxPower(
87+
RandomLoadProfile loadProfile, Set<LoadProfileEntry<RandomLoadValues>> loadProfileEntries) {
88+
return Optional.of(Quantities.getQuantity(159d, PowerSystemUnits.WATT));
89+
}
90+
91+
@Override
92+
public Optional<ComparableQuantity<Energy>> getLoadProfileEnergyScaling(
93+
RandomLoadProfile loadProfile) {
94+
return Optional.of(Quantities.getQuantity(716.5416966513656, PowerSystemUnits.KILOWATTHOUR));
95+
}
96+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ protected String processMethodResult(Object methodReturnObject, Method method, S
261261
processVoltageLevel((VoltageLevel) methodReturnObject, fieldName));
262262
case "Point", "LineString" -> resultStringBuilder.append(
263263
geoJsonWriter.write((Geometry) methodReturnObject));
264-
case "LoadProfile", "BdewStandardLoadProfile" -> resultStringBuilder.append(
265-
((LoadProfile) methodReturnObject).getKey());
264+
case "LoadProfile", "BdewStandardLoadProfile", "RandomLoadProfile" -> resultStringBuilder
265+
.append(((LoadProfile) methodReturnObject).getKey());
266266
case "AssetTypeInput",
267267
"BmTypeInput",
268268
"ChpTypeInput",

src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import edu.ie3.datamodel.models.timeseries.repetitive.*;
1717
import edu.ie3.datamodel.models.value.*;
1818
import edu.ie3.datamodel.models.value.load.BdewLoadValues;
19+
import edu.ie3.datamodel.models.value.load.RandomLoadValues;
1920
import java.lang.reflect.Method;
2021
import java.util.*;
2122
import java.util.stream.Collectors;
@@ -51,7 +52,9 @@ public class TimeSeriesProcessor<
5152
new TimeSeriesProcessorKey(
5253
IndividualTimeSeries.class, TimeBasedValue.class, HeatAndSValue.class),
5354
new TimeSeriesProcessorKey(
54-
BdewLoadProfileTimeSeries.class, LoadProfileEntry.class, BdewLoadValues.class));
55+
BdewLoadProfileTimeSeries.class, LoadProfileEntry.class, BdewLoadValues.class),
56+
new TimeSeriesProcessorKey(
57+
RandomLoadProfileTimeSeries.class, LoadProfileEntry.class, RandomLoadValues.class));
5558

5659
/**
5760
* Specific combination of time series class, entry class and value class, this processor is

src/main/java/edu/ie3/datamodel/models/profile/LoadProfile.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010
import java.util.Arrays;
1111
import java.util.stream.Collectors;
12+
import java.util.stream.Stream;
1213

1314
public interface LoadProfile extends Serializable {
1415
/** @return The identifying String */
@@ -28,12 +29,12 @@ static LoadProfile parse(String key) throws ParsingException {
2829
}
2930

3031
static LoadProfile[] getAllProfiles() {
31-
final LoadProfile[][] all =
32-
new LoadProfile[][] {
33-
BdewStandardLoadProfile.values(), NbwTemperatureDependantLoadProfile.values()
34-
};
35-
36-
return Arrays.stream(all).flatMap(Arrays::stream).toArray(LoadProfile[]::new);
32+
return Stream.of(
33+
BdewStandardLoadProfile.values(),
34+
NbwTemperatureDependantLoadProfile.values(),
35+
(LoadProfile[]) RandomLoadProfile.values())
36+
.flatMap(Arrays::stream)
37+
.toArray(LoadProfile[]::new);
3738
}
3839

3940
/**
@@ -70,4 +71,13 @@ public String getKey() {
7071
return "No load profile assigned";
7172
}
7273
}
74+
75+
enum RandomLoadProfile implements LoadProfile {
76+
RANDOM_LOAD_PROFILE;
77+
78+
@Override
79+
public String getKey() {
80+
return "random";
81+
}
82+
}
7383
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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.timeseries.repetitive;
7+
8+
import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution;
9+
import edu.ie3.datamodel.models.profile.LoadProfile;
10+
import edu.ie3.datamodel.models.value.load.RandomLoadValues;
11+
import edu.ie3.util.quantities.PowerSystemUnits;
12+
import java.util.Objects;
13+
import java.util.Optional;
14+
import java.util.Set;
15+
import java.util.UUID;
16+
import tech.units.indriya.quantity.Quantities;
17+
18+
/**
19+
* Describes a random load profile time series based on a {@link
20+
* GeneralizedExtremeValueDistribution}. Each value of this# timeseries is given in kW.
21+
*/
22+
public class RandomLoadProfileTimeSeries extends LoadProfileTimeSeries<RandomLoadValues> {
23+
24+
public RandomLoadProfileTimeSeries(
25+
UUID uuid, LoadProfile loadProfile, Set<LoadProfileEntry<RandomLoadValues>> entries) {
26+
super(
27+
uuid,
28+
loadProfile,
29+
entries,
30+
Optional.empty(),
31+
Optional.of(Quantities.getQuantity(716.5416966513656, PowerSystemUnits.KILOWATTHOUR)));
32+
}
33+
34+
@Override
35+
public LoadProfile.RandomLoadProfile getLoadProfile() {
36+
return (LoadProfile.RandomLoadProfile) super.getLoadProfile();
37+
}
38+
39+
@Override
40+
public boolean equals(Object o) {
41+
if (this == o) return true;
42+
if (o == null || getClass() != o.getClass()) return false;
43+
return super.equals(o);
44+
}
45+
46+
@Override
47+
public int hashCode() {
48+
return Objects.hash(super.hashCode());
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return "RandomLoadProfileTimeSeries{"
54+
+ "uuid="
55+
+ getUuid()
56+
+ "loadProfile="
57+
+ getLoadProfile()
58+
+ ", valueMapping="
59+
+ getValueMapping()
60+
+ '}';
61+
}
62+
}

0 commit comments

Comments
 (0)