Skip to content

Commit

Permalink
Adding random load profile. Adapting some tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
staudtMarius committed Aug 26, 2024
1 parent e2c8564 commit 8ecea73
Show file tree
Hide file tree
Showing 37 changed files with 1,024 additions and 619 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ dependencies {
// Graphs
implementation 'org.jgrapht:jgrapht-core:1.5.2'

// Statistics (for random load model)
implementation 'de.lmu.ifi.dbs.elki:elki:0.7.5'

// testing
testImplementation "org.apache.groovy:groovy:$groovyBinaryVersion"

Expand Down
46 changes: 40 additions & 6 deletions docs/uml/main/TimeSeriesDatamodelConcept.puml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,22 @@ package models {
childNote .. input
childNote .. voltagelevels

interface StandardLoadProfile {
interface LoadProfile {
+ getKey: String
+ {static} parse(String): LoadProfile
+ {static} getAllProfiles: LoadProfile[]
+ {static} getProfile(T[], String): T
+ enum DefaultLoadProfiles
+ enum RandomLoadProfile
}

DefaultLoadProfiles --|> LoadProfile
RandomLoadProfile --|> LoadProfile

interface StandardLoadProfile {
+ {static} parse(String): StandardLoadProfile
}
StandardLoadProfile ..|> LoadProfile

enum BdewLoadProfile {
- key: String
Expand Down Expand Up @@ -120,12 +131,22 @@ package models {
}
RepetitiveTimeSeries --|> TimeSeries

class LoadProfileInput {
- type: StandardLoadProfile
- dayOfWeekToHourlyValues: Map<DayOfWeek, Map<Integer, PValue>>
abstract class LoadProfileTimeSeries<E extends LoadProfileEntry> {
- loadProfile: StandardLoadProfile
- valueMapping: Map<Key, Map<Integer, E>>
+ getLoadProfile(): LoadProfile
# fromTime(ZonedDateTime): Key
}
LoadProfileInput --|> RepetitiveTimeSeries
LoadProfileInput *-- StandardLoadProfile
LoadProfileTimeSeries --|> RepetitiveTimeSeries
LoadProfileTimeSeries *-- LoadProfile

class BDEWLoadProfileTimeSeries {}
BDEWLoadProfileTimeSeries --|> LoadProfileTimeSeries
BDEWLoadProfileTimeSeries *-- BdewLoadProfileEntry

class RandomLoadProfileTimeSeries {}
RandomLoadProfileTimeSeries --|> LoadProfileTimeSeries
RandomLoadProfileTimeSeries *-- RandomLoadProfileEntry

abstract class TimeSeriesEntry <V extends Value> {
# value: V
Expand All @@ -142,8 +163,21 @@ package models {
class LoadProfileEntry {
- dayOfWeek: DayOfWeek
- quarterHourOfDay: int
+ getDayOfWeek(): DayOfWeek
+ getQuarterHourOfDay(): Integer
}
LoadProfileEntry --|> TimeSeriesEntry: <<bind>>:PValue

class BdewLoadProfileEntry {
- season: Season
+ getSeason(): Season
}
BdewLoadProfileEntry --|> LoadProfileEntry

class RandomLoadProfileEntry {
- gev: GeneralizedExtremeValueDistribution
}
RandomLoadProfileEntry --|> LoadProfileEntry
}
}

Expand Down
14 changes: 0 additions & 14 deletions docs/uml/main/input/InputDatamodelConcept.puml
Original file line number Diff line number Diff line change
Expand Up @@ -142,20 +142,6 @@ package models {
MeasurementUnitInput --|> AssetInput
MeasurementUnitInput ..|> HasNodes

class RandomLoadParameter {
- quarterHour: int
- kWd: Double
- kSa: Double
- kSu: Double
- myWd: Double
- mySa: Double
- mySu: Double
- sigmaWd: Double
- sigmaSa: Double
- sigmaSu: Double
}
RandomLoadParameter --|> InputEntity

abstract class AssetTypeInput {
- id: String
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
import static edu.ie3.util.quantities.PowerSystemUnits.KILOWATT;
import static java.time.DayOfWeek.*;

import edu.ie3.datamodel.exceptions.FactoryException;
import edu.ie3.datamodel.exceptions.ParsingException;
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileTimeSeriesMetaInformation;
import edu.ie3.datamodel.models.Season;
import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile;
import edu.ie3.datamodel.models.timeseries.repetitive.BDEWLoadProfileEntry;
import edu.ie3.datamodel.models.timeseries.repetitive.BDEWLoadProfileTimeSeries;
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries;
import edu.ie3.datamodel.models.value.PValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public class BDEWLoadProfileFactory
extends LoadProfileFactory<BdewStandardLoadProfile, BDEWLoadProfileEntry> {
Expand All @@ -31,82 +32,71 @@ public class BDEWLoadProfileFactory
public static final String TRANSITION_SATURDAY = "TrSa";
public static final String TRANSITION_SUNDAY = "TrSu";

public BDEWLoadProfileFactory() {
this(BDEWLoadProfileEntry.class);
}

public BDEWLoadProfileFactory(Class<BDEWLoadProfileEntry> valueClass) {
super(valueClass);
}

@Override
protected List<BDEWLoadProfileEntry> buildModel(LoadProfileData<BDEWLoadProfileEntry> data) {
List<BDEWLoadProfileEntry> entries = new ArrayList<>();
protected Set<BDEWLoadProfileEntry> buildModel(LoadProfileData<BDEWLoadProfileEntry> data) {
int quarterHour = data.getInt(QUARTER_HOUR);

/* summer */
entries.add(
return Set.of(
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(SUMMER_WEEKDAY, KILOWATT)),
Season.SUMMER,
MONDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(SUMMER_SATURDAY, KILOWATT)),
Season.SUMMER,
SATURDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(SUMMER_SUNDAY, KILOWATT)),
Season.SUMMER,
SUNDAY,
quarterHour));

/* winter */
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(WINTER_WEEKDAY, KILOWATT)),
Season.WINTER,
MONDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(WINTER_SATURDAY, KILOWATT)),
Season.WINTER,
SATURDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(WINTER_SUNDAY, KILOWATT)),
Season.WINTER,
SUNDAY,
quarterHour));

/* transition */
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(TRANSITION_WEEKDAY, KILOWATT)),
Season.TRANSITION,
MONDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(TRANSITION_SATURDAY, KILOWATT)),
Season.TRANSITION,
SATURDAY,
quarterHour));
entries.add(
quarterHour),
new BDEWLoadProfileEntry(
new PValue(data.getQuantity(TRANSITION_SUNDAY, KILOWATT)),
Season.TRANSITION,
SUNDAY,
quarterHour));

return entries;
}

@Override
protected List<Set<String>> getFields(Class<?> entityClass) {
return List.of(
newSet(
QUARTER_HOUR,
SUMMER_WEEKDAY,
SUMMER_SATURDAY,
SUMMER_SUNDAY,
Expand All @@ -120,7 +110,17 @@ protected List<Set<String>> getFields(Class<?> entityClass) {

@Override
public LoadProfileTimeSeries<BDEWLoadProfileEntry> build(
UUID uuid, BdewStandardLoadProfile loadProfile, Set<BDEWLoadProfileEntry> entries) {
return new BDEWLoadProfileTimeSeries(uuid, loadProfile, entries);
LoadProfileTimeSeriesMetaInformation metaInformation, Set<BDEWLoadProfileEntry> entries) {
return new BDEWLoadProfileTimeSeries(
metaInformation.getUuid(), parseProfile(metaInformation.getProfile()), entries);
}

@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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@
package edu.ie3.datamodel.io.factory.timeseries;

import edu.ie3.datamodel.io.factory.Factory;
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileTimeSeriesMetaInformation;
import edu.ie3.datamodel.models.profile.LoadProfile;
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry;
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public abstract class LoadProfileFactory<P extends LoadProfile, E extends LoadProfileEntry>
extends Factory<E, LoadProfileData<E>, List<E>> {
extends Factory<E, LoadProfileData<E>, Set<E>> {
public static final String QUARTER_HOUR = "quarterHour";

public LoadProfileFactory(Class<? extends E> valueClass) {

Check warning on line 19 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/LoadProfileFactory.java#L19

Change the visibility of this constructor to "protected".
super(valueClass);
}

public abstract LoadProfileTimeSeries<E> build(UUID uuid, P loadProfile, Set<E> entries);
public abstract LoadProfileTimeSeries<E> build(
LoadProfileTimeSeriesMetaInformation metaInformation, Set<E> data);

public abstract P parseProfile(String profile);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* © 2024. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.factory.timeseries;

import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE;
import static java.time.DayOfWeek.*;

import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution;
import de.lmu.ifi.dbs.elki.utilities.random.RandomFactory;
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileTimeSeriesMetaInformation;
import edu.ie3.datamodel.models.profile.LoadProfile;
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries;
import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileEntry;
import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries;
import java.util.List;
import java.util.Random;
import java.util.Set;

public class RandomLoadProfileFactory
extends LoadProfileFactory<LoadProfile, RandomLoadProfileEntry> {
public static final String K_WEEKDAY = "kWd";
public static final String K_SATURDAY = "kSa";
public static final String K_SUNDAY = "kSu";
public static final String MY_WEEKDAY = "myWd";
public static final String MY_SATURDAY = "mySa";
public static final String MY_SUNDAY = "mySu";
public static final String SIGMA_WEEKDAY = "sigmaWd";
public static final String SIGMA_SATURDAY = "sigmaSa";
public static final String SIGMA_SUNDAY = "sigmaSu";

public RandomLoadProfileFactory() {
super(RandomLoadProfileEntry.class);
}

@Override
protected Set<RandomLoadProfileEntry> buildModel(LoadProfileData<RandomLoadProfileEntry> data) {
int quarterHour = data.getInt(QUARTER_HOUR);
return Set.of(
new RandomLoadProfileEntry(
new GeneralizedExtremeValueDistribution(
data.getDouble(MY_WEEKDAY),
data.getDouble(SIGMA_WEEKDAY),
data.getDouble(K_WEEKDAY),
RandomFactory.get(new Random().nextLong())),

Check failure on line 47 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L47

Make sure that using this pseudorandom number generator is safe here.

Check failure on line 47 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L47

Save and re-use this "Random".
MONDAY,
quarterHour),
new RandomLoadProfileEntry(
new GeneralizedExtremeValueDistribution(
data.getDouble(MY_SATURDAY),
data.getDouble(SIGMA_SATURDAY),
data.getDouble(K_SATURDAY),
RandomFactory.get(new Random().nextLong())),

Check failure on line 55 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L55

Make sure that using this pseudorandom number generator is safe here.

Check failure on line 55 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L55

Save and re-use this "Random".
SATURDAY,
quarterHour),
new RandomLoadProfileEntry(
new GeneralizedExtremeValueDistribution(
data.getDouble(MY_SUNDAY),
data.getDouble(SIGMA_SUNDAY),
data.getDouble(K_SUNDAY),
RandomFactory.get(new Random().nextLong())),

Check failure on line 63 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L63

Make sure that using this pseudorandom number generator is safe here.

Check failure on line 63 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L63

Save and re-use this "Random".

Check warning on line 63 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/RandomLoadProfileFactory.java#L63

Random object created and used only once in edu.ie3.datamodel.io.factory.timeseries.RandomLoadProfileFactory.buildModel(LoadProfileData)
SUNDAY,
quarterHour));
}

@Override
protected List<Set<String>> getFields(Class<?> entityClass) {
return List.of(
newSet(
QUARTER_HOUR,
K_WEEKDAY,
K_SATURDAY,
K_SUNDAY,
MY_WEEKDAY,
MY_SATURDAY,
MY_SUNDAY,
SIGMA_WEEKDAY,
SIGMA_SATURDAY,
SIGMA_SUNDAY));
}

@Override
public LoadProfileTimeSeries<RandomLoadProfileEntry> build(
LoadProfileTimeSeriesMetaInformation metaInformation, Set<RandomLoadProfileEntry> entries) {
return new RandomLoadProfileTimeSeries(metaInformation.getUuid(), RANDOM_LOAD_PROFILE, entries);
}

@Override
public LoadProfile parseProfile(String profile) {
return RANDOM_LOAD_PROFILE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import edu.ie3.datamodel.models.result.system.*;
import edu.ie3.datamodel.models.result.thermal.ThermalUnitResult;
import edu.ie3.datamodel.models.timeseries.TimeSeries;
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileInput;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -250,9 +249,7 @@ private enum SubDirectories {
StorageTypeInput.class,
WecTypeInput.class,
OperatorInput.class,
WecCharacteristicInput.class,
RandomLoadParameters.class,
LoadProfileInput.class)
WecCharacteristicInput.class)
.collect(Collectors.toSet())),
PARTICIPANTS_INPUT(
Constants.INPUT_SUB_TREE.resolve("participants"),
Expand Down
Loading

0 comments on commit 8ecea73

Please sign in to comment.