Skip to content

Commit 4a1adb6

Browse files
Merge branch 'dev' into rel/df/#1398-release_8.1.0
# Conflicts: # version.properties
2 parents 0b70b03 + fd1758c commit 4a1adb6

File tree

57 files changed

+2476
-1080
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2476
-1080
lines changed

CHANGELOG.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased/Snapshot]
88

99
### Added
10-
11-
### Fixed
10+
- Enhanced check for invalid field names in sources [#1383](https://github.com/ie3-institute/PowerSystemDataModel/issues/1383)
11+
- Enhancing value retrieval in `TimeSeriesSource` [1280](https://github.com/ie3-institute/PowerSystemDataModel/issues/1280)
12+
- Enhancing the `LoadProfileSource` to return the resolution [1288](https://github.com/ie3-institute/PowerSystemDataModel/issues/1288)
13+
- Enhancing Validation for sRated of `HpTypeInput` [1394](https://github.com/ie3-institute/PowerSystemDataModel/issues/1394)
14+
- Added updated `BdewStandardLoadProfiles` [#1292](https://github.com/ie3-institute/PowerSystemDataModel/issues/1292)
1215

1316
### Changed
17+
- Fixed CFF-Version [#1392](https://github.com/ie3-institute/PowerSystemDataModel/issues/1392)
18+
- Enhanced `ValidationUtils` for `LoadModel` to check for correct profile naming [#1357](https://github.com/ie3-institute/PowerSystemDataModel/issues/1357)
1419

1520
## [8.0.0] - 2025-07-22
1621

1722
### Added
1823
- Extend Validation to EnergyManagement Systems. [#1356](https://github.com/ie3-institute/PowerSystemDataModel/issues/1356)
24+
- Added `CITATION.cff` [#1380](https://github.com/ie3-institute/PowerSystemDataModel/issues/1380)
1925

2026
### Fixed
2127
- Fixed handling of `CongestionResult.InputModelType` in `EntityProcessor` [#1325](https://github.com/ie3-institute/PowerSystemDataModel/issues/1325)
@@ -379,7 +385,7 @@ coordinates or multiple exactly equal coordinates possible
379385
- CsvDataSource now stops trying to get an operator for empty operator uuid field in entities
380386
- CsvDataSource now parsing multiple geoJson strings correctly
381387

382-
[Unreleased/Snapshot]:
388+
[Unreleased/Snapshot]: https://github.com/ie3-institute/powersystemdatamodel/compare/8.0.0...HEAD
383389
[8.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/7.0.0...8.0.0
384390
[7.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/6.0.0...7.0.0
385391
[6.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.1.0...6.0.0

CITATION.cff

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
cff-version: 1.2.0
2+
title: "PowerSystemDataModel - Provides an elaborated data model to model energy systems with a high granularity."
3+
message: "If you use this software, please cite it as below."
4+
type: software
5+
authors:
6+
- name: "ie³ - Institute of Energy Systems, Energy Efficiency and Energy Economics - TU Dortmund University"
7+
alias: ie³
8+
address: "Martin-Schmeißer-Weg 12"
9+
city: Dortmund
10+
country: DE
11+
post-code: 44227
12+
website: "https://ie3.etit.tu-dortmund.de/"
13+
- family-names: Hiry
14+
given-names: Johannes
15+
orcid: https://orcid.org/0000-0002-1447-0607
16+
- family-names: Kittl
17+
given-names: Chris
18+
orcid: https://orcid.org/0000-0002-1187-0568
19+
- family-names: Sen-Sarma
20+
given-names: Debopama
21+
- family-names: Peter
22+
given-names: Sebastian
23+
orcid: https://orcid.org/0000-0001-6311-6113
24+
- family-names: Oberließen
25+
given-names: Thomas
26+
orcid: https://orcid.org/0000-0001-5805-5408
27+
- family-names: Feismann
28+
given-names: Daniel
29+
orcid: https://orcid.org/0000-0002-3531-9025
30+
- family-names: Bao
31+
given-names: Johannes
32+
orcid: https://orcid.org/0009-0008-3641-6469
33+
- family-names: Hohmann
34+
given-names: Julian
35+
- family-names: Staudt
36+
given-names: Marius
37+
orcid: https://orcid.org/0009-0005-3309-5258
38+
- family-names: Steffan
39+
given-names: Niklas
40+
- family-names: Kraus
41+
given-names: Mia
42+
- family-names: Strehle
43+
given-names: Dennis
44+
- family-names: Mahr
45+
given-names: Christian
46+
- family-names: Zachopoulos
47+
given-names: Vasilios
48+
- family-names: Bajpai
49+
given-names: Shubham
50+
- family-names: Roumeliotis
51+
given-names: Lara
52+
- family-names: Bung
53+
given-names: Vicky
54+
- family-names: Hütte
55+
given-names: Simon
56+
- family-names: Petersmeier
57+
given-names: Pierre
58+
repository-code: https://github.com/ie3-institute/PowerSystemDataModel
59+
keywords:
60+
- power system data model
61+
- power system
62+
- energy system
63+
license: BSD-3-Clause
64+
version: 7.0.0
65+
date-released: 2025-06-05

build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
id 'maven-publish'
55
id 'signing'
66
id 'pmd' // code check, working on source code
7-
id 'com.diffplug.spotless' version '7.1.0' //code format
7+
id 'com.diffplug.spotless' version '7.2.1' //code format
88
id 'com.github.spotbugs' version '6.2.2' // code check, working on byte code
99
id 'de.undercouch.download' version '5.6.0'
1010
id 'kr.motd.sphinx' version '2.10.1' // documentation generation
@@ -18,7 +18,7 @@ ext {
1818
//version (changing these should be considered thoroughly!)
1919
javaVersion = JavaVersion.VERSION_17
2020
groovyVersion = "4.0"
21-
groovyBinaryVersion = "4.0.27"
21+
groovyBinaryVersion = "4.0.28"
2222

2323
junitVersion = '1.12.0'
2424
testcontainersVersion = '1.21.3'
@@ -102,8 +102,8 @@ dependencies {
102102
implementation 'com.couchbase.client:java-client:3.8.3'
103103
runtimeOnly 'org.postgresql:postgresql:42.7.7' // postgresql jdbc driver required during runtime
104104

105-
implementation 'commons-io:commons-io:2.19.0' // I/O functionalities
106-
implementation 'commons-codec:commons-codec:1.18.0' // needed by commons-compress
105+
implementation 'commons-io:commons-io:2.20.0' // I/O functionalities
106+
implementation 'commons-codec:commons-codec:1.19.0' // needed by commons-compress
107107
implementation 'org.apache.commons:commons-compress:1.27.1' // I/O functionalities
108108
}
109109

docs/readthedocs/io/csvfiles.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,11 @@ The following profiles are supported until now:
169169
- Information
170170
- Supported head line.
171171
* - e.g.: H0
172-
- BDEW standard load profiles ([source](https://www.bdew.de/energie/standardlastprofile-strom/))
172+
- BDEW standard load profiles 1999 ([source](https://www.bdew.de/energie/standardlastprofile-strom/))
173173
- Permissible head line: ``SuSa,SuSu,SuWd,TrSa,TrSu,TrWd,WiSa,WiSu,WiWd,quarterHour``
174+
* - e.g.: h25
175+
- BDEW standard load profiles 2025 ([source](https://www.bdew.de/energie/standardlastprofile-strom/))
176+
- Permissible head line: ``janSa,janSu,janWd,febSa,febSu,febWd,marSa,marSu,marWd,aprSa,aprSu,aprWd,maySa,maySu,mayWd,junSa,junSu,junWd,julSa,julSu,julWd,augSa,augSu,augWd,sepSa,sepSu,sepWd,octSa,octSu,octWd,novSa,novSu,novWd,decSa,decSu,decWd,quarterHour``
174177
* - random
175178
- A random load proile based on: ``Kays - Agent-based simulation environment for improving the planning of distribution grids``
176179
- Permissible head line: ``kSa,kSu,kWd,mySa,mySu,myWd,sigmaSa,sigmaSu,sigmaWd,quarterHour``

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,11 @@ public Try<Void, ValidationException> validate(
174174
+ "' are possible (NOT case-sensitive!):\n"
175175
+ possibleOptions));
176176
} else {
177+
// find all unused fields
177178
Set<String> unused = getUnusedFields(harmonizedActualFields, validFieldSets);
178179

179180
if (!unused.isEmpty()) {
180-
log.debug(
181+
log.info(
181182
"The following additional fields were found for entity class of '{}': {}",
182183
entityClass.getSimpleName(),
183184
unused);

src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantInputEntityFactory.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,26 @@ public abstract class SystemParticipantInputEntityFactory<
3030
T extends SystemParticipantInput, D extends SystemParticipantEntityData>
3131
extends AssetInputEntityFactory<T, D> {
3232

33+
private static final String NODE = "node";
34+
3335
private static final String Q_CHARACTERISTICS = "qCharacteristics";
3436

3537
public static final String CONTROLLING_EM = "controllingEm";
3638

39+
@SafeVarargs
3740
protected SystemParticipantInputEntityFactory(Class<? extends T>... allowedClasses) {
3841
super(allowedClasses);
3942
}
4043

4144
@Override
4245
protected List<Set<String>> getFields(Class<?> entityClass) {
4346
List<Set<String>> fields = new ArrayList<>(super.getFields(entityClass));
44-
for (Set<String> set : fields) set.add(Q_CHARACTERISTICS);
45-
46-
List<Set<String>> withEm =
47-
fields.stream().map(f -> (Set<String>) expandSet(f, CONTROLLING_EM)).toList();
4847

49-
fields.addAll(withEm);
48+
for (Set<String> set : fields) {
49+
set.add(Q_CHARACTERISTICS);
50+
set.add(NODE);
51+
set.add(CONTROLLING_EM);
52+
}
5053

5154
return fields;
5255
}

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

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,66 +15,57 @@
1515
import edu.ie3.datamodel.models.timeseries.repetitive.BdewLoadProfileTimeSeries;
1616
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry;
1717
import edu.ie3.datamodel.models.value.load.BdewLoadValues;
18-
import java.util.*;
18+
import edu.ie3.datamodel.models.value.load.BdewLoadValues.BdewKey;
19+
import edu.ie3.datamodel.models.value.load.BdewLoadValues.BdewScheme;
20+
import edu.ie3.util.quantities.PowerSystemUnits;
21+
import java.util.Comparator;
22+
import java.util.HashSet;
23+
import java.util.List;
24+
import java.util.Set;
1925
import java.util.function.Function;
20-
import java.util.stream.Stream;
2126
import javax.measure.quantity.Energy;
2227
import javax.measure.quantity.Power;
2328
import tech.units.indriya.ComparableQuantity;
2429
import tech.units.indriya.quantity.Quantities;
2530

2631
public class BdewLoadProfileFactory
2732
extends LoadProfileFactory<BdewStandardLoadProfile, BdewLoadValues> {
28-
public static final String SUMMER_SATURDAY = "SuSa";
29-
public static final String SUMMER_SUNDAY = "SuSu";
30-
public static final String SUMMER_WEEKDAY = "SuWd";
31-
public static final String TRANSITION_SATURDAY = "TrSa";
32-
public static final String TRANSITION_SUNDAY = "TrSu";
33-
public static final String TRANSITION_WEEKDAY = "TrWd";
34-
public static final String WINTER_SATURDAY = "WiSa";
35-
public static final String WINTER_SUNDAY = "WiSu";
36-
public static final String WINTER_WEEKDAY = "WiWd";
33+
// 1999 profile scheme
34+
public static final BdewLoadValues.BdewMap<String> BDEW1999_FIELDS =
35+
BdewKey.toMap(BdewScheme.BDEW1999);
3736

38-
public BdewLoadProfileFactory() {
39-
this(BdewLoadValues.class);
40-
}
37+
// 2025 profile scheme
38+
public static final BdewLoadValues.BdewMap<String> BDEW2025_FIELDS =
39+
BdewKey.toMap(BdewScheme.BDEW2025);
4140

42-
public BdewLoadProfileFactory(Class<BdewLoadValues> valueClass) {
43-
super(valueClass);
41+
public BdewLoadProfileFactory() {
42+
super(BdewLoadValues.class);
4443
}
4544

4645
@Override
4746
protected LoadProfileEntry<BdewLoadValues> buildModel(LoadProfileData<BdewLoadValues> data) {
4847
int quarterHour = data.getInt(QUARTER_HOUR);
4948

50-
return new LoadProfileEntry<>(
51-
new BdewLoadValues(
52-
data.getDouble(SUMMER_SATURDAY),
53-
data.getDouble(SUMMER_SUNDAY),
54-
data.getDouble(SUMMER_WEEKDAY),
55-
data.getDouble(TRANSITION_SATURDAY),
56-
data.getDouble(TRANSITION_SUNDAY),
57-
data.getDouble(TRANSITION_WEEKDAY),
58-
data.getDouble(WINTER_SATURDAY),
59-
data.getDouble(WINTER_SUNDAY),
60-
data.getDouble(WINTER_WEEKDAY)),
61-
quarterHour);
49+
boolean is1999Scheme =
50+
data.containsKey("SuSa") || data.containsKey("su_sa") || data.containsKey("suSa");
51+
52+
BdewLoadValues values;
53+
54+
if (is1999Scheme) {
55+
values = new BdewLoadValues(BdewScheme.BDEW1999, BDEW1999_FIELDS.map(data::getDouble));
56+
57+
} else {
58+
values = new BdewLoadValues(BdewScheme.BDEW2025, BDEW2025_FIELDS.map(data::getDouble));
59+
}
60+
61+
return new LoadProfileEntry<>(values, quarterHour);
6262
}
6363

6464
@Override
6565
protected List<Set<String>> getFields(Class<?> entityClass) {
6666
return List.of(
67-
newSet(
68-
QUARTER_HOUR,
69-
SUMMER_SATURDAY,
70-
SUMMER_SUNDAY,
71-
SUMMER_WEEKDAY,
72-
TRANSITION_SATURDAY,
73-
TRANSITION_SUNDAY,
74-
TRANSITION_WEEKDAY,
75-
WINTER_SATURDAY,
76-
WINTER_SUNDAY,
77-
WINTER_WEEKDAY));
67+
expandSet(new HashSet<>(BDEW1999_FIELDS.values()), QUARTER_HOUR),
68+
expandSet(new HashSet<>(BDEW2025_FIELDS.values()), QUARTER_HOUR));
7869
}
7970

8071
@Override
@@ -101,26 +92,35 @@ public BdewStandardLoadProfile parseProfile(String profile) {
10192
@Override
10293
public ComparableQuantity<Power> calculateMaxPower(
10394
BdewStandardLoadProfile loadProfile, Set<LoadProfileEntry<BdewLoadValues>> entries) {
104-
Function<BdewLoadValues, Stream<Double>> valueExtractor;
105-
106-
if (loadProfile == BdewStandardLoadProfile.H0) {
107-
// maximum dynamization factor is on day 366 (leap year) or day 365 (regular year).
108-
// The difference between day 365 and day 366 is negligible, thus pick 366
109-
valueExtractor =
110-
v ->
111-
Stream.of(v.getWiSa(), v.getWiSu(), v.getWiWd())
112-
.map(p -> BdewLoadValues.dynamization(p, 366));
113-
} else {
114-
valueExtractor = v -> v.values().stream();
115-
}
95+
Function<BdewLoadValues, Double> valueExtractor =
96+
switch (loadProfile) {
97+
case H0, H25, P25, S25 ->
98+
// maximum dynamization factor is on day 366 (leap year) or day 365 (regular year).
99+
// The difference between day 365 and day 366 is negligible, thus pick 366
100+
v -> BdewLoadValues.dynamization(v.getMaxValue(true), 366);
101+
default -> v -> v.getMaxValue(false);
102+
};
116103

117104
double maxPower =
118105
entries.stream()
119106
.map(TimeSeriesEntry::getValue)
120-
.flatMap(valueExtractor)
107+
.map(valueExtractor)
121108
.max(Comparator.naturalOrder())
122109
.orElse(0d);
123110

124111
return Quantities.getQuantity(maxPower, WATT);
125112
}
113+
114+
/** Returns the load profile energy scaling. The default value is 1000 kWh */
115+
@Override
116+
public ComparableQuantity<Energy> getLoadProfileEnergyScaling(
117+
BdewStandardLoadProfile loadProfile) {
118+
119+
// the updated profiled are scaled to 1 million kWh -> 1000 MWh
120+
// old profiles are scaled to 1000 kWh
121+
return switch (loadProfile) {
122+
case H25, G25, L25, P25, S25 -> Quantities.getQuantity(1000d, PowerSystemUnits.MEGAWATTHOUR);
123+
default -> Quantities.getQuantity(1000d, PowerSystemUnits.KILOWATTHOUR);
124+
};
125+
}
126126
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public LoadProfileFactory(Class<? extends V> valueClass) {
3232
super(valueClass);
3333
}
3434

35+
@SafeVarargs
36+
protected LoadProfileFactory(Class<? extends V>... valueClass) {
37+
super(valueClass);
38+
}
39+
3540
public abstract LoadProfileTimeSeries<V> build(
3641
LoadProfileMetaInformation metaInformation, Set<LoadProfileEntry<V>> entries);
3742

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
import edu.ie3.datamodel.models.Entity;
1010
import edu.ie3.datamodel.models.StandardUnits;
1111
import edu.ie3.datamodel.utils.Try;
12-
import edu.ie3.datamodel.utils.Try.*;
12+
import edu.ie3.datamodel.utils.Try.Failure;
13+
import edu.ie3.datamodel.utils.Try.Success;
1314
import edu.ie3.util.exceptions.QuantityException;
14-
import java.lang.reflect.Method;
15-
import java.util.*;
15+
import java.util.Collections;
16+
import java.util.LinkedHashMap;
17+
import java.util.SortedMap;
1618
import javax.measure.Quantity;
1719
import javax.measure.quantity.Energy;
1820
import javax.measure.quantity.Power;
@@ -31,7 +33,7 @@ public abstract class EntityProcessor<T extends Entity> extends Processor<T> {
3133

3234
public static final Logger log = LoggerFactory.getLogger(EntityProcessor.class);
3335
protected final String[] headerElements;
34-
private final SortedMap<String, Method> fieldNameToMethod;
36+
private final SortedMap<String, GetterMethod> fieldNameToMethod;
3537

3638
private static final String NODE_INTERNAL = "nodeInternal";
3739

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* © 2025. 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.processor;
7+
8+
import java.lang.reflect.InvocationTargetException;
9+
import java.lang.reflect.Method;
10+
11+
public record GetterMethod(String name, Getter getter, String returnType) {
12+
13+
public GetterMethod(Method method) {
14+
this(method.getName(), method::invoke, method.getReturnType().getSimpleName());
15+
}
16+
17+
public Object invoke(Object object)
18+
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
19+
return getter.get(object);
20+
}
21+
22+
@FunctionalInterface
23+
public interface Getter {
24+
Object get(Object object)
25+
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
26+
}
27+
}

0 commit comments

Comments
 (0)