Skip to content

Add Attributes housingType and numberInhabitants to ThermalHouses #1254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `BdewLoadProfileTimeSeries` [#1230](https://github.com/ie3-institute/PowerSystemDataModel/issues/1230)
- Added `RandomLoadProfileTimeSeries` [#1232](https://github.com/ie3-institute/PowerSystemDataModel/issues/1232)
- Attribute `pThermalRated` for `ThermalStorage`s [#679](https://github.com/ie3-institute/PowerSystemDataModel/issues/679)
- Attributes `housingType` and `numberInhabitants` for `ThermalHouse`s [#1253](https://github.com/ie3-institute/PowerSystemDataModel/issues/1253)

### Fixed
- Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221)
Expand Down
2 changes: 1 addition & 1 deletion docs/readthedocs/io/ValidationUtils.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The ValidationUtils include validation checks for...
- HpTypeInput
- StorageTypeInput
- WecTypeInput
- ThermalUnitValidationUtils
- ThermalValidationUtils
- ThermalUnitInput
- ThermalSinkInput
- ThermalHouseInput
Expand Down
8 changes: 8 additions & 0 deletions docs/readthedocs/models/input/thermal/thermalhouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ This reflects a simple shoe box with transmission losses
* - lowerTemperatureLimit
- °C
- Lower temperature boundary

* - housingType
- –
- Type of building can either be house or flat

* - numberInhabititans
- –
- Number of people living in the house. Double values to enable modeling based on statistical data sources.

```

Expand Down
2 changes: 2 additions & 0 deletions docs/uml/main/input/ThermalDatamodelConcept.puml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ package models {
- targetTemperature: ComparableQuantity<Temperature> [°C]
- upperTemperatureLimit: ComparableQuantity<Temperature> [°C]
- lowerTemperatureLimit: ComparableQuantity<Temperature> [°C]
- houseType: String ['house' or 'flat']
- numberInhabitants: Double
}
ThermalHouseInput --|> ThermalSinkInput

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public class ThermalHouseInputFactory
private static final String TARGET_TEMPERATURE = "targetTemperature";
private static final String UPPER_TEMPERATURE_LIMIT = "upperTemperatureLimit";
private static final String LOWER_TEMPERATURE_LIMIT = "lowerTemperatureLimit";
private static final String HOUSING_TYPE = "housingType";
private static final String NUMBER_INHABITANTS = "numberInhabitants";

public ThermalHouseInputFactory() {
super(ThermalHouseInput.class);
Expand All @@ -31,7 +33,13 @@ public ThermalHouseInputFactory() {
@Override
protected String[] getAdditionalFields() {
return new String[] {
ETH_LOSSES, ETH_CAPA, TARGET_TEMPERATURE, UPPER_TEMPERATURE_LIMIT, LOWER_TEMPERATURE_LIMIT
ETH_LOSSES,
ETH_CAPA,
TARGET_TEMPERATURE,
UPPER_TEMPERATURE_LIMIT,
LOWER_TEMPERATURE_LIMIT,
HOUSING_TYPE,
NUMBER_INHABITANTS
};
}

Expand All @@ -53,6 +61,8 @@ protected ThermalHouseInput buildModel(
data.getQuantity(UPPER_TEMPERATURE_LIMIT, StandardUnits.TEMPERATURE);
final ComparableQuantity<Temperature> lowerTemperatureLimit =
data.getQuantity(LOWER_TEMPERATURE_LIMIT, StandardUnits.TEMPERATURE);
final String housingType = data.getField(HOUSING_TYPE);
final double numberInhabitants = data.getDouble(NUMBER_INHABITANTS);
return new ThermalHouseInput(
uuid,
id,
Expand All @@ -63,6 +73,8 @@ protected ThermalHouseInput buildModel(
ethCapa,
targetTemperature,
upperTemperatureLimit,
lowerTemperatureLimit);
lowerTemperatureLimit,
housingType,
numberInhabitants);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public class ThermalHouseInput extends ThermalSinkInput {
private final ComparableQuantity<Temperature> upperTemperatureLimit;
/** Lower boundary temperature of the thermal house model (typically in °C) */
private final ComparableQuantity<Temperature> lowerTemperatureLimit;
/** Type of the building, e.g. house or flat */
private final String housingType;
/** Number of people living in the building, double to allow proper scaling */
private final double numberInhabitants;

/**
* @param uuid Unique identifier of a thermal house model
Expand All @@ -37,6 +41,8 @@ public class ThermalHouseInput extends ThermalSinkInput {
* @param targetTemperature Desired target temperature of the thermal house model
* @param upperTemperatureLimit Upper boundary temperature of the thermal house model
* @param lowerTemperatureLimit Lower boundary temperature of the thermal house model
* @param housingType Type of the building: either house or flat
* @param numberInhabitants Number of inhabitants living in this house
*/
public ThermalHouseInput(
UUID uuid,
Expand All @@ -46,13 +52,17 @@ public ThermalHouseInput(
ComparableQuantity<HeatCapacity> ethCapa,
ComparableQuantity<Temperature> targetTemperature,
ComparableQuantity<Temperature> upperTemperatureLimit,
ComparableQuantity<Temperature> lowerTemperatureLimit) {
ComparableQuantity<Temperature> lowerTemperatureLimit,
String housingType,
double numberInhabitants) {
super(uuid, id, bus);
this.ethLosses = ethLosses.to(StandardUnits.THERMAL_TRANSMISSION);
this.ethCapa = ethCapa.to(StandardUnits.HEAT_CAPACITY);
this.targetTemperature = targetTemperature.to(StandardUnits.TEMPERATURE);
this.upperTemperatureLimit = upperTemperatureLimit.to(StandardUnits.TEMPERATURE);
this.lowerTemperatureLimit = lowerTemperatureLimit.to(StandardUnits.TEMPERATURE);
this.housingType = housingType;
this.numberInhabitants = numberInhabitants;
}

/**
Expand All @@ -66,6 +76,8 @@ public ThermalHouseInput(
* @param targetTemperature Desired target temperature of the thermal house model
* @param upperTemperatureLimit Upper boundary temperature of the thermal house model
* @param lowerTemperatureLimit Lower boundary temperature of the thermal house model
* @param housingType Type of the building: either house or flat
* @param numberInhabitants Number of inhabitants living in this house
*/
public ThermalHouseInput(
UUID uuid,
Expand All @@ -77,13 +89,17 @@ public ThermalHouseInput(
ComparableQuantity<HeatCapacity> ethCapa,
ComparableQuantity<Temperature> targetTemperature,
ComparableQuantity<Temperature> upperTemperatureLimit,
ComparableQuantity<Temperature> lowerTemperatureLimit) {
ComparableQuantity<Temperature> lowerTemperatureLimit,
String housingType,
double numberInhabitants) {
super(uuid, id, operator, operationTime, bus);
this.ethLosses = ethLosses.to(StandardUnits.THERMAL_TRANSMISSION);
this.ethCapa = ethCapa.to(StandardUnits.HEAT_CAPACITY);
this.targetTemperature = targetTemperature.to(StandardUnits.TEMPERATURE);
this.upperTemperatureLimit = upperTemperatureLimit.to(StandardUnits.TEMPERATURE);
this.lowerTemperatureLimit = lowerTemperatureLimit.to(StandardUnits.TEMPERATURE);
this.housingType = housingType;
this.numberInhabitants = numberInhabitants;
}

public ComparableQuantity<ThermalConductance> getEthLosses() {
Expand All @@ -106,6 +122,14 @@ public ComparableQuantity<Temperature> getLowerTemperatureLimit() {
return lowerTemperatureLimit;
}

public String getHousingType() {
return housingType;
}

public double getNumberOfInhabitants() {
return numberInhabitants;
}

@Override
public ThermalHouseInputCopyBuilder copy() {
return new ThermalHouseInputCopyBuilder(this);
Expand All @@ -120,7 +144,9 @@ public boolean equals(Object o) {
&& ethCapa.equals(that.ethCapa)
&& targetTemperature.equals(that.targetTemperature)
&& upperTemperatureLimit.equals(that.upperTemperatureLimit)
&& lowerTemperatureLimit.equals(that.lowerTemperatureLimit);
&& lowerTemperatureLimit.equals(that.lowerTemperatureLimit)
&& Objects.equals(housingType, that.housingType)
&& Objects.equals(numberInhabitants, that.numberInhabitants);
}

@Override
Expand All @@ -131,7 +157,9 @@ public int hashCode() {
ethCapa,
targetTemperature,
upperTemperatureLimit,
lowerTemperatureLimit);
lowerTemperatureLimit,
housingType,
numberInhabitants);
}

@Override
Expand All @@ -157,6 +185,10 @@ public String toString() {
+ upperTemperatureLimit
+ ", lowerTemperatureLimit="
+ lowerTemperatureLimit
+ ", housingType="
+ housingType
+ ", #inhabitants="
+ numberInhabitants
+ '}';
}

Expand All @@ -173,6 +205,8 @@ public static class ThermalHouseInputCopyBuilder
private ComparableQuantity<Temperature> targetTemperature;
private ComparableQuantity<Temperature> upperTemperatureLimit;
private ComparableQuantity<Temperature> lowerTemperatureLimit;
private String housingType;
private double numberInhabitants;

private ThermalHouseInputCopyBuilder(ThermalHouseInput entity) {
super(entity);
Expand All @@ -181,6 +215,8 @@ private ThermalHouseInputCopyBuilder(ThermalHouseInput entity) {
this.targetTemperature = entity.getTargetTemperature();
this.upperTemperatureLimit = entity.getUpperTemperatureLimit();
this.lowerTemperatureLimit = entity.getLowerTemperatureLimit();
this.housingType = entity.getHousingType();
this.numberInhabitants = entity.getNumberOfInhabitants();
}

public ThermalHouseInputCopyBuilder ethLosses(
Expand Down Expand Up @@ -212,12 +248,23 @@ public ThermalHouseInputCopyBuilder lowerTemperatureLimit(
return this;
}

public ThermalHouseInputCopyBuilder housingType(String housingType) {
this.housingType = housingType;
return this;
}

public ThermalHouseInputCopyBuilder numberInhabitants(double numberInhabitants) {
this.numberInhabitants = numberInhabitants;
return this;
}

@Override
public ThermalHouseInputCopyBuilder scale(Double factor) {
// scale losses as well as capacity to keep equal
// scale losses as well as capacity and number of inhabitants to keep equal
// the time needed to heat a scaled house
ethLosses(ethLosses.multiply(factor));
ethCapa(ethCapa.multiply(factor));
numberInhabitants(numberInhabitants * factor);
return this;
}

Expand All @@ -233,7 +280,9 @@ public ThermalHouseInput build() {
ethCapa,
targetTemperature,
upperTemperatureLimit,
lowerTemperatureLimit);
lowerTemperatureLimit,
housingType,
numberInhabitants);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import edu.ie3.datamodel.utils.Try.Failure;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.measure.Quantity;

public class ThermalValidationUtils extends ValidationUtils {
Expand Down Expand Up @@ -172,6 +173,8 @@ private ThermalValidationUtils() {
* <li>its thermal capacity is positive
* <li>its upper temperature limit is higher than the lower temperature limit
* <li>its target temperature lies between the upper und lower limit temperatures
* <li>its housing type is either `house` or `flat`
* <li>its number of inhabitants is higher than zero
* </ul>
*
* @param thermalHouseInput ThermalHouseInput to validate
Expand Down Expand Up @@ -210,9 +213,33 @@ private static List<Try<Void, InvalidEntityException>> checkThermalHouse(
thermalHouseInput)));
}

if (!isValidHousingType(thermalHouseInput.getHousingType())) {
exceptions.add(
new Failure<>(
new InvalidEntityException(
"Housing type must be either 'house' or 'flat'", thermalHouseInput)));
}

if (thermalHouseInput.getNumberOfInhabitants() <= 0) {
exceptions.add(
new Failure<>(
new InvalidEntityException(
"Number of inhabitants must be greater than zero", thermalHouseInput)));
}

return exceptions;
}

/**
* Checks if the housing type is valid (either "house" or "flat").
*
* @param housingType The housing type to check
* @return true if valid, false otherwise
*/
private static boolean isValidHousingType(String housingType) {
return Set.of("house", "flat").contains(housingType.toLowerCase());
}

/**
* Validates a cylindricalStorageInput if:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class ThermalHouseInputFactoryTest extends Specification implements FactoryTestH
"ethcapa" : "4",
"targetTemperature" : "5",
"upperTemperatureLimit": "6",
"lowerTemperatureLimit": "7"
"lowerTemperatureLimit": "7",
"housingType" : "flat",
"numberInhabitants" : "9",

]
def inputClass = ThermalHouseInput
def thermalBusInput = Mock(ThermalBusInput)
Expand All @@ -57,6 +60,8 @@ class ThermalHouseInputFactoryTest extends Specification implements FactoryTestH
assert targetTemperature == getQuant(parameter["targetTemperature"], StandardUnits.TEMPERATURE)
assert upperTemperatureLimit == getQuant(parameter["upperTemperatureLimit"], StandardUnits.TEMPERATURE)
assert lowerTemperatureLimit == getQuant(parameter["lowerTemperatureLimit"], StandardUnits.TEMPERATURE)
assert housingType == parameter["housingType"]
assert numberInhabitants == parameter["numberInhabitants"].toDouble()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class CsvThermalSourceTest extends Specification implements CsvTestDataMeta {
targetTemperature == ThermalUnitInputTestData.thermalHouseInput.targetTemperature
upperTemperatureLimit == ThermalUnitInputTestData.thermalHouseInput.upperTemperatureLimit
lowerTemperatureLimit == ThermalUnitInputTestData.thermalHouseInput.lowerTemperatureLimit
housingType == ThermalUnitInputTestData.thermalHouseInput.housingType
numberOfInhabitants == ThermalUnitInputTestData.thermalHouseInput.numberOfInhabitants
}

//test method when operators and thermal buses are provided as constructor parameters
Expand All @@ -135,6 +137,8 @@ class CsvThermalSourceTest extends Specification implements CsvTestDataMeta {
targetTemperature == ThermalUnitInputTestData.thermalHouseInput.targetTemperature
upperTemperatureLimit == ThermalUnitInputTestData.thermalHouseInput.upperTemperatureLimit
lowerTemperatureLimit == ThermalUnitInputTestData.thermalHouseInput.lowerTemperatureLimit
housingType == ThermalUnitInputTestData.thermalHouseInput.housingType
numberOfInhabitants == ThermalUnitInputTestData.thermalHouseInput.numberOfInhabitants
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ThermalHouseInputTest extends Specification {
assert targetTemperature == ThermalUnitInputTestData.TARGET_TEMPERATURE
assert upperTemperatureLimit == ThermalUnitInputTestData.UPPER_TEMPERATURE_LIMIT
assert lowerTemperatureLimit == ThermalUnitInputTestData.LOWER_TEMPERATURE_LIMIT
assert housingType == ThermalUnitInputTestData.HOUSING_TYPE
assert numberOfInhabitants == ThermalUnitInputTestData.NUMBER_INHABITANTS
}
}

Expand Down Expand Up @@ -67,12 +69,17 @@ class ThermalHouseInputTest extends Specification {
Quantities.getQuantity(20, StandardUnits.HEAT_CAPACITY),
Quantities.getQuantity(20, StandardUnits.TEMPERATURE),
Quantities.getQuantity(25, StandardUnits.TEMPERATURE),
Quantities.getQuantity(15, StandardUnits.TEMPERATURE))
Quantities.getQuantity(15, StandardUnits.TEMPERATURE),
"house",
2.0
)

expect:
thermalHouseInput.targetTemperature == Quantities.getQuantity(20, StandardUnits.TEMPERATURE)
thermalHouseInput.upperTemperatureLimit == Quantities.getQuantity(25, StandardUnits.TEMPERATURE)
thermalHouseInput.lowerTemperatureLimit == Quantities.getQuantity(15, StandardUnits.TEMPERATURE)
thermalHouseInput.housingType == "house"
thermalHouseInput.numberOfInhabitants == 2.0
}

def "Scaling a ThermalHouseInput via builder should work as expected"() {
Expand All @@ -94,6 +101,8 @@ class ThermalHouseInputTest extends Specification {
assert targetTemperature == thermalHouseInput.targetTemperature
assert upperTemperatureLimit == thermalHouseInput.upperTemperatureLimit
assert lowerTemperatureLimit == thermalHouseInput.lowerTemperatureLimit
assert housingType == thermalHouseInput.housingType
assert numberOfInhabitants == thermalHouseInput.numberOfInhabitants * 2d
}
}
}
Loading