Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6bb6984
Add ground temperature (1m) as option to weather data.
pierrepetersmeier Jun 18, 2025
0342ae2
Merge branch 'dev' into 1343-add-ground-temperature-1m-as-option-to-w…
pierrepetersmeier Jun 26, 2025
920be80
Address review feedback and align test suite
pierrepetersmeier Jul 2, 2025
e259bee
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Jul 2, 2025
1b8dd09
fixing the comments and tests.
pierrepetersmeier Jul 9, 2025
6a77ffc
fmt
pierrepetersmeier Jul 9, 2025
d46b0d1
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Jul 10, 2025
9f767ed
Meeting
pierrepetersmeier Jul 11, 2025
b015b66
Add GroundTemperatureValue and refactor WeatherValue, CosmoTimeBasedW…
pierrepetersmeier Jul 16, 2025
8e33409
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Jul 16, 2025
b0d87d9
Remove logger.warn
pierrepetersmeier Jul 28, 2025
0399aa3
fmt
pierrepetersmeier Aug 12, 2025
813cdbe
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Aug 12, 2025
88191d1
fmt
pierrepetersmeier Aug 12, 2025
47ac942
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Aug 18, 2025
41302fe
fmt
pierrepetersmeier Aug 25, 2025
3c153a3
Merge remote-tracking branch 'origin/pp/#1343-add-ground-temperature-…
pierrepetersmeier Aug 25, 2025
83b3736
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Sep 24, 2025
13f27ee
Merge remote-tracking branch 'origin/pp/#1343-add-ground-temperature-…
pierrepetersmeier Oct 1, 2025
55a7c15
Add GroundTemperatureValue 0cm and 80cm.
pierrepetersmeier Oct 17, 2025
cde88f0
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Oct 17, 2025
f0698b4
Fix SqlSinkTest
pierrepetersmeier Oct 19, 2025
1d9ff09
fmt
pierrepetersmeier Oct 19, 2025
4ec2c68
fmt
pierrepetersmeier Oct 19, 2025
f939e57
fmt
danielfeismann Oct 20, 2025
55bb4e1
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
danielfeismann Oct 20, 2025
71ab33a
Apply suggestion from @danielfeismann
pierrepetersmeier Oct 22, 2025
224aa30
Update src/test/resources/edu/ie3/datamodel/io/source/csv/_weather/co…
pierrepetersmeier Oct 22, 2025
6039cc2
Update src/test/resources/edu/ie3/datamodel/io/sink/_sql/time_series.sql
pierrepetersmeier Oct 22, 2025
46fb11f
remove unused function
pierrepetersmeier Oct 22, 2025
082451a
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Oct 22, 2025
3a0e1e9
remove unused function and refactoring tests
pierrepetersmeier Oct 31, 2025
57640e2
fmt
pierrepetersmeier Nov 2, 2025
7f11669
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Nov 2, 2025
1c5c4ba
InfluxDB
pierrepetersmeier Nov 2, 2025
3be844f
TestData
pierrepetersmeier Nov 2, 2025
3f04286
fmt
pierrepetersmeier Nov 2, 2025
c8f0d18
fmt
pierrepetersmeier Nov 2, 2025
c067c0b
fmt
pierrepetersmeier Nov 2, 2025
64c0172
fmt
pierrepetersmeier Nov 2, 2025
d691a2c
Update src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java
pierrepetersmeier Nov 4, 2025
e80cb33
Merge branch 'dev' into pp/#1343-add-ground-temperature-1m-as-option-…
pierrepetersmeier Nov 4, 2025
42e8599
Optional
pierrepetersmeier Nov 4, 2025
ae9da09
FlatMap instead of Map. Optional in Tests.
pierrepetersmeier Nov 4, 2025
481ab12
enhancing TimeSeriesProcessor
danielfeismann Nov 4, 2025
5efc4d2
sonar
danielfeismann Nov 4, 2025
41d031e
optinal empty
danielfeismann Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Extend Validation to EnergyManagement Systems. [#1356](https://github.com/ie3-institute/PowerSystemDataModel/issues/1356)
- Add ground temperature (1m) as option to weather data. [#1343](https://github.com/ie3-institute/PowerSystemDataModel/issues/1343)

### Fixed
- Fixed handling of `CongestionResult.InputModelType` in `EntityProcessor` [#1325](https://github.com/ie3-institute/PowerSystemDataModel/issues/1325)
Expand Down
11 changes: 10 additions & 1 deletion docs/readthedocs/models/input/additionaldata/weathersource.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,14 @@ Weather data is comprised of five key components:
* - **`windDirection`**
- Wind direction, where 0° is North, 90° is East, etc.
- ° (degrees)

* - **`groundTemperatureValueOne`**
- Ground temperature at 0cm for this coordinate.
- K (Kelvin)

* - **`groundTemperatureValueTwo`**
- Ground temperature at 0cm for this coordinate.
- K (Kelvin)
```
Weather data in COSMO and ICON formats is supported. Additional optional weather data can also be provided.
Weather data in COSMO and ICON formats is supported. Additional optional weather data can also be provided.
The ground temperature measurements at 0 cm and 80 cm depth are used because underground cables are typically laid at around 80 cm depth.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this need some update since know its possible to use different depths, right?

Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import edu.ie3.util.quantities.interfaces.Irradiance;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Speed;
Expand All @@ -32,6 +33,8 @@ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFact
private static final String TEMPERATURE = "temperature";
private static final String WIND_DIRECTION = "windDirection";
private static final String WIND_VELOCITY = "windVelocity";
private static final String GROUND_TEMPERATURE_VALUE_ONE = "groundTemperature0cm";
private static final String GROUND_TEMPERATURE_VALUE_TWO = "groundTemperature80cm";

public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) {
super(timeUtil);
Expand All @@ -55,7 +58,11 @@ protected List<Set<String>> getFields(Class<?> entityClass) {
TEMPERATURE,
WIND_DIRECTION,
WIND_VELOCITY);
return Collections.singletonList(minConstructorParams);

Set<String> withGroundTemp =
expandSet(minConstructorParams, GROUND_TEMPERATURE_VALUE_ONE, GROUND_TEMPERATURE_VALUE_TWO);

return Arrays.asList(minConstructorParams, withGroundTemp);
}

@Override
Expand All @@ -72,14 +79,21 @@ protected TimeBasedValue<WeatherValue> buildModel(TimeBasedWeatherValueData data
data.getQuantity(WIND_DIRECTION, StandardUnits.WIND_DIRECTION);
ComparableQuantity<Speed> windVelocity =
data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY);
Optional<ComparableQuantity<Temperature>> groundTempValOne =
data.getQuantityOptional(GROUND_TEMPERATURE_VALUE_ONE, StandardUnits.TEMPERATURE);
Optional<ComparableQuantity<Temperature>> groundTempValTwo =
data.getQuantityOptional(GROUND_TEMPERATURE_VALUE_TWO, StandardUnits.TEMPERATURE);
WeatherValue weatherValue =
new WeatherValue(
coordinate,
directIrradiance,
diffuseIrradiance,
temperature,
windDirection,
windVelocity);
windVelocity,
groundTempValOne,
groundTempValTwo);

return new TimeBasedValue<>(time, weatherValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFacto
private static final String TEMPERATURE = "t2m";
private static final String WIND_VELOCITY_U = "u131m";
private static final String WIND_VELOCITY_V = "v131m";
private static final String GROUND_TEMPERATURE_VALUE_ONE = "t_v1";
private static final String GROUND_TEMPERATURE_VALUE_TWO = "t_v2";
Comment on lines +36 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about tg_1, tg_2?


public IconTimeBasedWeatherValueFactory() {
super();
Expand All @@ -53,7 +55,8 @@ protected List<Set<String>> getFields(Class<?> entityClass) {
"albrad",
"asobs",
"aswdifuS",
"tG",
"t_v1",
"t_v2",
"u10m",
"u20m",
"u216m",
Expand Down Expand Up @@ -88,14 +91,21 @@ protected TimeBasedValue<WeatherValue> buildModel(TimeBasedWeatherValueData data
data.getQuantity(TEMPERATURE, Units.KELVIN).to(StandardUnits.TEMPERATURE);
ComparableQuantity<Angle> windDirection = getWindDirection(data);
ComparableQuantity<Speed> windVelocity = getWindVelocity(data);
Optional<ComparableQuantity<Temperature>> groundTemperatureValueOne =
data.getQuantityOptional(GROUND_TEMPERATURE_VALUE_ONE, Units.KELVIN);
Optional<ComparableQuantity<Temperature>> groundTemperatureValueTwo =
data.getQuantityOptional(GROUND_TEMPERATURE_VALUE_TWO, Units.KELVIN);

WeatherValue weatherValue =
new WeatherValue(
coordinate,
directIrradiance,
diffuseIrradiance,
temperature,
windDirection,
windVelocity);
windVelocity,
groundTemperatureValueOne,
groundTemperatureValueTwo);
return new TimeBasedValue<>(time, weatherValue);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ public enum FieldSource {
WEATHER_IRRADIANCE,
WEATHER_TEMPERATURE,
WEATHER_WIND,
GROUND_TEMPERATURE_ONE,
GROUND_TEMPERATURE_TWO,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,17 @@ private SortedMap<String, FieldSourceToMethod> buildFieldToSource(
.forEach(addFunction.apply(WEATHER_IRRADIANCE));
mapFieldNameToGetter(TemperatureValue.class).forEach(addFunction.apply(WEATHER_TEMPERATURE));
mapFieldNameToGetter(WindValue.class).forEach(addFunction.apply(WEATHER_WIND));
Map<String, GetterMethod> groundTempMap = mapFieldNameToGetter(GroundTemperatureValue.class);
groundTempMap.forEach(
(fieldName, getter) ->
addFunction
.apply(GROUND_TEMPERATURE_ONE)
.accept("groundTemperatureValueOne", getter));
groundTempMap.forEach(
(fieldName, getter) ->
addFunction
.apply(GROUND_TEMPERATURE_TWO)
.accept("groundTemperatureValueTwo", getter));

} else if (valueClass.equals(BdewLoadValues.class)) {

Expand Down Expand Up @@ -272,6 +283,20 @@ private Map<String, String> handleEntry(T timeSeries, E entry) throws EntityProc

Map<String, GetterMethod> windFieldToMethod = extractFieldToMethod(WEATHER_WIND);
valueResult.putAll(processObject(weatherValue.getWind(), windFieldToMethod));

Map<String, GetterMethod> groundTempOneFieldToMethod =
extractFieldToMethod(GROUND_TEMPERATURE_ONE);
Optional<GroundTemperatureValue> gtOneOpt = weatherValue.getGroundTemperatureValueOne();
if (gtOneOpt.isPresent()) {
valueResult.putAll(processObject(gtOneOpt.get(), groundTempOneFieldToMethod));
}

Map<String, GetterMethod> groundTempTwoFieldToMethod =
extractFieldToMethod(GROUND_TEMPERATURE_TWO);
Optional<GroundTemperatureValue> gtTwoOpt = weatherValue.getGroundTemperatureValueTwo();
if (gtTwoOpt.isPresent()) {
valueResult.putAll(processObject(gtTwoOpt.get(), groundTempTwoFieldToMethod));
}
}

/* Join all information and sort them */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* © 2025. 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 javax.measure.quantity.Temperature;
import tech.units.indriya.ComparableQuantity;

/**
* Describes a ground temperature value. This class extends {@link TemperatureValue} to represent
* temperature at a specific depth in the ground.
*/
public class GroundTemperatureValue extends TemperatureValue {

/**
* Constructs a new GroundTemperatureValue.
*
* @param temperature The temperature quantity (typically in K)
*/
public GroundTemperatureValue(ComparableQuantity<Temperature> temperature) {
super(temperature);
}

@Override
public String toString() {
return "GroundTemperatureValue{" + "temperature=" + getTemperature().orElse(null) + '}';
}
}
53 changes: 48 additions & 5 deletions src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import edu.ie3.util.quantities.interfaces.Irradiance;
import java.util.Objects;
import java.util.Optional;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Speed;
import javax.measure.quantity.Temperature;
Expand All @@ -27,44 +28,66 @@
/** Wind values for this coordinate */
private final WindValue wind;

/** Ground temperature value for this coordinate */
private final Optional<GroundTemperatureValue> groundTemperatureValueOne;

Check failure on line 32 in src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java

View check run for this annotation

SonarQubeGithubPRChecks / SonarQube Code Analysis

src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java#L32

Make non-static "groundTemperatureValueOne" transient or serializable.

/** Ground temperature value for this coordinate */
private final Optional<GroundTemperatureValue> groundTemperatureValueTwo;

Check failure on line 35 in src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java

View check run for this annotation

SonarQubeGithubPRChecks / SonarQube Code Analysis

src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java#L35

Make non-static "groundTemperatureValueTwo" transient or serializable.

/**
* @param coordinate of this weather value set
* @param solarIrradiance values for this coordinate
* @param temperature values for this coordinate
* @param wind values for this coordinate
* @param groundTemperatureValueOne values for this coordinate (can be null)
* @param groundTemperatureValueTwo values for this coordinate (can be null)
*/
public WeatherValue(
Point coordinate,
SolarIrradianceValue solarIrradiance,
TemperatureValue temperature,
WindValue wind) {
WindValue wind,
Optional<GroundTemperatureValue> groundTemperatureValueOne,
Optional<GroundTemperatureValue> groundTemperatureValueTwo) {
this.coordinate = coordinate;
this.solarIrradiance = solarIrradiance;
this.temperature = temperature;
this.wind = wind;
this.groundTemperatureValueOne = groundTemperatureValueOne;
this.groundTemperatureValueTwo = groundTemperatureValueTwo;
}

/**
* Constructor with all parameters as quantities.
*
* @param coordinate of this weather value set
* @param directSolarIrradiance Direct sun irradiance for this coordinate (typically in W/m²)
* @param diffuseSolarIrradiance Diffuse sun irradiance for this coordinate (typically in W/m²)
* @param temperature for this coordinate (typically in K)
* @param direction Direction, the wind comes from as an angle from north increasing clockwise
* (typically in rad)
* @param velocity Wind velocity for this coordinate (typically in m/s)
* @param groundTempValOne Ground temperature for this coordinate (typically in K, can be null)
* @param groundTempValTwo Ground temperature for this coordinate (typically in K, can be null)
*/
public WeatherValue(
Point coordinate,
ComparableQuantity<Irradiance> directSolarIrradiance,
ComparableQuantity<Irradiance> diffuseSolarIrradiance,
ComparableQuantity<Temperature> temperature,
ComparableQuantity<Angle> direction,
ComparableQuantity<Speed> velocity) {
ComparableQuantity<Speed> velocity,
Optional<ComparableQuantity<Temperature>> groundTempValOne,
Optional<ComparableQuantity<Temperature>> groundTempValTwo) {
this(
coordinate,
new SolarIrradianceValue(directSolarIrradiance, diffuseSolarIrradiance),
new TemperatureValue(temperature),
new WindValue(direction, velocity));
new WindValue(direction, velocity),
Optional.ofNullable(groundTempValOne)
.flatMap(optional -> optional.map(GroundTemperatureValue::new)),
Optional.ofNullable(groundTempValTwo)
.flatMap(optional -> optional.map(GroundTemperatureValue::new)));
}

public Point getCoordinate() {
Expand All @@ -83,6 +106,14 @@
return wind;
}

public Optional<GroundTemperatureValue> getGroundTemperatureValueOne() {
return groundTemperatureValueOne;
}

public Optional<GroundTemperatureValue> getGroundTemperatureValueTwo() {
return groundTemperatureValueTwo;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -91,12 +122,20 @@
return coordinate.equals(that.coordinate)
&& solarIrradiance.equals(that.solarIrradiance)
&& temperature.equals(that.temperature)
&& wind.equals(that.wind);
&& wind.equals(that.wind)
&& Objects.equals(groundTemperatureValueOne, that.groundTemperatureValueOne)
&& Objects.equals(groundTemperatureValueTwo, that.groundTemperatureValueTwo);
}

@Override
public int hashCode() {
return Objects.hash(coordinate, solarIrradiance, temperature, wind);
return Objects.hash(
coordinate,
solarIrradiance,
temperature,
wind,
groundTemperatureValueOne,
groundTemperatureValueTwo);
}

@Override
Expand All @@ -110,6 +149,10 @@
+ temperature
+ ", wind="
+ wind
+ ", groundTemperatureValueOne="
+ groundTemperatureValueOne
+ ", groundTemperatureValueTwo="
+ groundTemperatureValueTwo
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification {
"directIrradiance" : "286.872985839844",
"temperature" : "",
"windDirection" : "0",
"windVelocity" : "1.66103506088257"
"windVelocity" : "1.66103506088257",
"groundTemperatureValueOne" : "",
"groundTemperatureValueTwo" : ""
]

def data = new TimeBasedWeatherValueData(parameter, coordinate)
Expand All @@ -39,7 +41,9 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification {
Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE),
null,
Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION),
Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY)))
Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY),
Optional.empty(),
Optional.empty()))

when:
def model = factory.buildModel(data)
Expand All @@ -61,7 +65,9 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification {
"directIrradiance" : "286.872985839844",
"temperature" : "278.019012451172",
"windDirection" : "0",
"windVelocity" : "1.66103506088257"
"windVelocity" : "1.66103506088257",
"groundTemperatureValueOne" : "",
"groundTemperatureValueTwo" : ""
]

def data = new TimeBasedWeatherValueData(parameter, coordinate)
Expand All @@ -72,7 +78,9 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification {
Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE),
Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE),
Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION),
Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY)))
Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY),
Optional.of(Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE)),
Optional.of(Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE))))

when:
def model = factory.buildModel(data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification {
"aswdirS" : "2.317613203124999",
"t2m" : "289.1179319051744",
"tg" : "288.4101691197649",
"t_v1":"288.4101691197649",
"t_v2":"288.4101691197649",
"u10m" : "0.3021732864307963",
"u131m" : "2.6058700426057797",
"u20m" : "0.32384365019387784",
Expand Down Expand Up @@ -125,6 +127,10 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification {
assert QuantityUtil.isEquivalentAbs(it.value.wind.direction.get(), Quantities.getQuantity(214.16711674907722, PowerSystemUnits.DEGREE_GEOM))
assert it.value.wind.velocity.present
assert QuantityUtil.isEquivalentAbs(it.value.wind.velocity.get(), Quantities.getQuantity(4.640010877529081, PowerSystemUnits.METRE_PER_SECOND))
assert it.value.groundTemperatureValueOne.present
assert QuantityUtil.isEquivalentAbs(it.value.groundTemperatureValueOne.get().temperature.get(), Quantities.getQuantity(15.2601691197649, Units.CELSIUS))
assert it.value.groundTemperatureValueTwo.present
assert QuantityUtil.isEquivalentAbs(it.value.groundTemperatureValueTwo.get().temperature.get(), Quantities.getQuantity(15.2601691197649, Units.CELSIUS))
}
}
}
Loading