diff --git a/CHANGELOG.md b/CHANGELOG.md index 6da8da6db..642923271 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,8 @@ 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) +- Attributes `housingType` and `numberInhabitants` for `ThermalHouse`s [#1253](https://github.com/ie3-institute/PowerSystemDataModel/issues/1253) +- Added domestic hot water storage model [#1257](https://github.com/ie3-institute/PowerSystemDataModel/issues/1257) ### Fixed - Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221) diff --git a/docs/readthedocs/models/input/thermal/domestichotwaterstorage.md b/docs/readthedocs/models/input/thermal/domestichotwaterstorage.md new file mode 100644 index 000000000..4b675451a --- /dev/null +++ b/docs/readthedocs/models/input/thermal/domestichotwaterstorage.md @@ -0,0 +1,64 @@ +(domestichotwaterstorage-model)= + +# Domestic Hot Water Storage + +Model of a domestic hot water storage using a fluid to store thermal energy. + +## Attributes, Units and Remarks + +```{eval-rst} +.. list-table:: + :widths: 33 33 33 + :header-rows: 1 + + + * - Attribute + - Unit + - Remarks + + * - uuid + - -- + - + + * - id + - -- + - Human readable identifier + + * - operator + - -- + - + + * - operationTime + - -- + - Timely restriction of operation + + * - thermalBus + - -- + - Connection point to the thermal system + + * - storageVolumeLvl + - m³ + - Overall available storage volume + + * - inletTemp + - °C + - Temperature of the inlet + + * - returnTemp + - °C + - Temperature of the outlet + + * - c + - kWh / (K :math:`\cdot` m³) + - Specific heat capacity of the storage medium + + * - pThermalMax + - kW + - Maximum permissible thermal power of the storage + +``` + +## Caveats + +Nothing - at least not known. +If you found something, please contact us! diff --git a/docs/readthedocs/models/models.md b/docs/readthedocs/models/models.md index 56c314ac9..390d650cb 100644 --- a/docs/readthedocs/models/models.md +++ b/docs/readthedocs/models/models.md @@ -129,6 +129,7 @@ maxdepth: 1 input/thermal/thermalbus input/thermal/thermalhouse input/thermal/cylindricalstorage +input/thermal/domestichotwaterstorage ``` ### Participant Related Models @@ -209,6 +210,7 @@ result/participant/thermalstorage result/participant/thermalunit result/participant/thermalhouse result/participant/cylindricalstorage +result/participant/domestichotwaterstorage result/participant/systemparticipant result/participant/flexoption result/participant/em diff --git a/docs/readthedocs/models/result/participant/domestichotwaterstorage.md b/docs/readthedocs/models/result/participant/domestichotwaterstorage.md new file mode 100644 index 000000000..f0cefcd59 --- /dev/null +++ b/docs/readthedocs/models/result/participant/domestichotwaterstorage.md @@ -0,0 +1,44 @@ +(domestichotwaterstorage-result)= + +# Domestic Hot Water Storage + +Result of a domestic hot water storage using a fluid to store thermal energy. + +## Attributes, Units and Remarks + +```{eval-rst} +.. list-table:: + :widths: 33 33 33 + :header-rows: 1 + + + * - Attribute + - Unit + - Remarks + + * - time + - -- + - date and time for the produced result + + * - inputModel + - -- + - uuid for the associated input model + + * - energy + - MWh + - + + * - qDot + - MW + - heat demand of the sink + + * - fillLevel + - -- + - + +``` + +## Caveats + +Nothing - at least not known. +If you found something, please contact us! diff --git a/docs/uml/main/EntitySourceClassDiagram.puml b/docs/uml/main/EntitySourceClassDiagram.puml index a9ae77130..d7c0de723 100644 --- a/docs/uml/main/EntitySourceClassDiagram.puml +++ b/docs/uml/main/EntitySourceClassDiagram.puml @@ -130,6 +130,7 @@ class ResultEntitySource { + Set getEvResults() throws SourceException + Set getHpResults() throws SourceException + Set getCylindricalStorageResult() throws SourceException + + Set getDomesticHotWaterStorageResult() throws SourceException + Set getThermalHouseResults() throws SourceException + Set getEmResults() throws SourceException + Set getCongestionResults() throws SourceException @@ -179,6 +180,7 @@ class ThermalSource { - TypeSource typeSource - ThermalBusInputFactory thermalBusInputFactory - CylindricalStorageInputFactory cylindricalStorageInputFactory + - DomesticHotWaterStorageInputFactory domesticHotWaterStorageInputFactory - ThermalHouseInputFactory thermalHouseInputFactory + ThermalSource(TypeSource, DataSource) + Map getThermalBuses() throws SourceException @@ -187,8 +189,10 @@ class ThermalSource { + Map getThermalStorages(Map, Map) throws SourceException + Map getThermalHouses() throws SourceException + Map getThermalHouses(Map, Map) throws SourceException - + Set getCylindricStorages() throws SourceException - + Set getCylindricStorages(Map, Map) throws SourceException + + Set getCylindricalStorages() throws SourceException + + Set getCylindricalStorages(Map, Map) throws SourceException + + Set getDomesticHotWaterStorages() throws SourceException + + Set getDomesticHotWaterStorages(Map, Map) throws SourceException } abstract class TimeSeriesMappingSource { diff --git a/docs/uml/main/OutputDatamodelConcept.puml b/docs/uml/main/OutputDatamodelConcept.puml index de0b7c745..5af946551 100644 --- a/docs/uml/main/OutputDatamodelConcept.puml +++ b/docs/uml/main/OutputDatamodelConcept.puml @@ -130,10 +130,16 @@ package models { } ThermalUnitResult <|-- ThermalStorageResult - class CylindricalStorageResult { + Abstract class AbstractThermalStorageResult { - fillLevel: ComparableQuantity [%] } - ThermalStorageResult <|-- CylindricalStorageResult + ThermalStorageResult <|-- AbstractThermalStorageResult + + class CylindricalStorageResult {} + AbstractThermalStorageResult <|-- CylindricalStorageResult + + class DomesticHotWaterStorageResult {} + AbstractThermalStorageResult <|-- DomesticHotWaterStorageResult } } } diff --git a/docs/uml/main/input/DefaultInputDirectoryHierarchy.puml b/docs/uml/main/input/DefaultInputDirectoryHierarchy.puml index f9bb14f35..f9b8a369b 100644 --- a/docs/uml/main/input/DefaultInputDirectoryHierarchy.puml +++ b/docs/uml/main/input/DefaultInputDirectoryHierarchy.puml @@ -9,7 +9,7 @@ package (.tar.gz) { label "line_input.csv\n//measurement_unit_input.csv//\nnode_input.csv\n//switch_input.csv//\ntransformer_2_w_input.csv\n//transformer_3_w_input.csv//" } package "//thermal//" as th { - label "//cylindrical_storage_input.csv//\n//thermal_bus_input.csv//\n//thermal_house_input.csv//" + label "//cylindrical_storage_input.csv//\n//domestic_hot_water_storage_input.csv//\n//thermal_bus_input.csv//\n//thermal_house_input.csv//" } package participants { label "//bm_input.csv//\n//chp_input.csv//\n//ev_input.csv//\n//evcs_input.csv//\n//fixed_feed_in_input.csv//\n//hp_input.csv//\n//load_input.csv//\n//pv_input.csv//\n//storage_input.csv//\n//wec_input.csv//" diff --git a/docs/uml/main/input/DefaultResultDirectoryHierarchy.puml b/docs/uml/main/input/DefaultResultDirectoryHierarchy.puml index ee194e413..08261fb74 100644 --- a/docs/uml/main/input/DefaultResultDirectoryHierarchy.puml +++ b/docs/uml/main/input/DefaultResultDirectoryHierarchy.puml @@ -6,7 +6,7 @@ package (.tar.gz) { label "//line_result.csv//\n//node_result.csv//\n//switch_result.csv//\n//transformer_2_w_result.csv//\n//transformer_3_w_result.csv//" } package "//thermal//" { - label "//cylindrical_storage_result.csv//\n//thermal_bus_result.csv//\n//thermal_house_result.csv//" + label "//cylindrical_storage_result.csv//\n//domestic_hot_water_storage_result.csv//\n//thermal_bus_result.csv//\n//thermal_house_result.csv//" } package "//participants//" { label "//bm_result.csv//\n//chp_result.csv//\n//ev_result.csv//\n//evcs_result.csv//\n//fixed_feed_in_result.csv//\n//hp_result.csv//\n//load_result.csv//\n//pv_result.csv//\n//storage_result.csv//\n//wec_result.csv//" diff --git a/docs/uml/main/input/ThermalDatamodelConcept.puml b/docs/uml/main/input/ThermalDatamodelConcept.puml index 11abcb7ac..5fafcb880 100644 --- a/docs/uml/main/input/ThermalDatamodelConcept.puml +++ b/docs/uml/main/input/ThermalDatamodelConcept.puml @@ -115,6 +115,9 @@ package models { abstract class ThermalStorageInput ThermalStorageInput --|> ThermalUnitInput + abstract class AbstractStorageInput + AbstractStorageInput --|> ThermalStorageInput + class CylindricalStorageInput { - storageVolumeLvl: ComparableQuantity [m³] - inletTemp: ComparableQuantity [°C] @@ -122,7 +125,16 @@ package models { - c: ComparableQuantity [kWh/(K*m³)] - pThermalMax: ComparableQuantity [kW] } - CylindricalStorageInput --|> ThermalStorageInput + CylindricalStorageInput --|> AbstractStorageInput + + class DomesticHotWaterStorageInput { + - storageVolumeLvl: ComparableQuantity [m³] + - inletTemp: ComparableQuantity [°C] + - returnTemp: ComparableQuantity [°C] + - c: ComparableQuantity [kWh/(K*m³)] + - pThermalMax: ComparableQuantity [kW] + } + DomesticHotWaterStorageInput --|> AbstractStorageInput } } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/AbstractThermalStorageInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/AbstractThermalStorageInputFactory.java new file mode 100644 index 000000000..f286217c7 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/AbstractThermalStorageInputFactory.java @@ -0,0 +1,54 @@ +/* + * © 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.input; + +import edu.ie3.datamodel.models.StandardUnits; +import edu.ie3.datamodel.models.input.AssetInput; +import edu.ie3.util.quantities.interfaces.SpecificHeatCapacity; +import javax.measure.quantity.Power; +import javax.measure.quantity.Temperature; +import javax.measure.quantity.Volume; +import tech.units.indriya.ComparableQuantity; + +public abstract class AbstractThermalStorageInputFactory + extends AssetInputEntityFactory { + + private static final String STORAGE_VOLUME_LVL = "storageVolumeLvl"; + private static final String INLET_TEMP = "inletTemp"; + private static final String RETURN_TEMP = "returnTemp"; + private static final String C = "c"; + private static final String P_THERMAL_MAX = "pThermalMax"; + + public AbstractThermalStorageInputFactory(Class clazz) { + super(clazz); + } + + @Override + protected String[] getAdditionalFields() { + return new String[] {STORAGE_VOLUME_LVL, INLET_TEMP, RETURN_TEMP, C, P_THERMAL_MAX}; + } + + protected ComparableQuantity getStorageVolumeLvl(ThermalUnitInputEntityData data) { + return data.getQuantity(STORAGE_VOLUME_LVL, StandardUnits.VOLUME); + } + + protected ComparableQuantity getInletTemp(ThermalUnitInputEntityData data) { + return data.getQuantity(INLET_TEMP, StandardUnits.TEMPERATURE); + } + + protected ComparableQuantity getReturnTemp(ThermalUnitInputEntityData data) { + return data.getQuantity(RETURN_TEMP, StandardUnits.TEMPERATURE); + } + + protected ComparableQuantity getSpecificHeatCapacity( + ThermalUnitInputEntityData data) { + return data.getQuantity(C, StandardUnits.SPECIFIC_HEAT_CAPACITY); + } + + protected ComparableQuantity getMaxThermalPower(ThermalUnitInputEntityData data) { + return data.getQuantity(P_THERMAL_MAX, StandardUnits.ACTIVE_POWER_IN); + } +} diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/CylindricalStorageInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/CylindricalStorageInputFactory.java index b41f1eecd..541aa7f56 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/CylindricalStorageInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/CylindricalStorageInputFactory.java @@ -6,34 +6,18 @@ package edu.ie3.datamodel.io.factory.input; import edu.ie3.datamodel.models.OperationTime; -import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput; import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; -import edu.ie3.util.quantities.interfaces.SpecificHeatCapacity; import java.util.UUID; -import javax.measure.quantity.Power; -import javax.measure.quantity.Temperature; -import javax.measure.quantity.Volume; -import tech.units.indriya.ComparableQuantity; public class CylindricalStorageInputFactory - extends AssetInputEntityFactory { - private static final String STORAGE_VOLUME_LVL = "storageVolumeLvl"; - private static final String INLET_TEMP = "inletTemp"; - private static final String RETURN_TEMP = "returnTemp"; - private static final String C = "c"; - private static final String P_THERMAL_MAX = "pThermalMax"; + extends AbstractThermalStorageInputFactory { public CylindricalStorageInputFactory() { super(CylindricalStorageInput.class); } - @Override - protected String[] getAdditionalFields() { - return new String[] {STORAGE_VOLUME_LVL, INLET_TEMP, RETURN_TEMP, C, P_THERMAL_MAX}; - } - @Override protected CylindricalStorageInput buildModel( ThermalUnitInputEntityData data, @@ -41,28 +25,18 @@ protected CylindricalStorageInput buildModel( String id, OperatorInput operator, OperationTime operationTime) { - final ThermalBusInput bus = data.getBusInput(); - final ComparableQuantity storageVolumeLvl = - data.getQuantity(STORAGE_VOLUME_LVL, StandardUnits.VOLUME); - final ComparableQuantity inletTemp = - data.getQuantity(INLET_TEMP, StandardUnits.TEMPERATURE); - final ComparableQuantity returnTemp = - data.getQuantity(RETURN_TEMP, StandardUnits.TEMPERATURE); - final ComparableQuantity c = - data.getQuantity(C, StandardUnits.SPECIFIC_HEAT_CAPACITY); - final ComparableQuantity pThermalMax = - data.getQuantity(P_THERMAL_MAX, StandardUnits.ACTIVE_POWER_IN); + final ThermalBusInput bus = data.getBusInput(); return new CylindricalStorageInput( uuid, id, operator, operationTime, bus, - storageVolumeLvl, - inletTemp, - returnTemp, - c, - pThermalMax); + getStorageVolumeLvl(data), + getInletTemp(data), + getReturnTemp(data), + getSpecificHeatCapacity(data), + getMaxThermalPower(data)); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactory.java new file mode 100644 index 000000000..b59ed35bb --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactory.java @@ -0,0 +1,42 @@ +/* + * © 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.input; + +import edu.ie3.datamodel.models.OperationTime; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput; +import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; +import java.util.UUID; + +public class DomesticHotWaterStorageInputFactory + extends AbstractThermalStorageInputFactory { + + public DomesticHotWaterStorageInputFactory() { + super(DomesticHotWaterStorageInput.class); + } + + @Override + protected DomesticHotWaterStorageInput buildModel( + ThermalUnitInputEntityData data, + UUID uuid, + String id, + OperatorInput operator, + OperationTime operationTime) { + + final ThermalBusInput bus = data.getBusInput(); + return new DomesticHotWaterStorageInput( + uuid, + id, + operator, + operationTime, + bus, + getStorageVolumeLvl(data), + getInletTemp(data), + getReturnTemp(data), + getSpecificHeatCapacity(data), + getMaxThermalPower(data)); + } +} diff --git a/src/main/java/edu/ie3/datamodel/io/factory/result/ThermalResultFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/result/ThermalResultFactory.java index 6a84b6d73..b2d52ad0d 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/result/ThermalResultFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/result/ThermalResultFactory.java @@ -10,6 +10,7 @@ import edu.ie3.datamodel.models.Entity; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult; +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult; import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult; import edu.ie3.datamodel.models.result.thermal.ThermalUnitResult; import java.time.ZonedDateTime; @@ -28,7 +29,10 @@ public class ThermalResultFactory extends ResultEntityFactory private static final String FILL_LEVEL = "fillLevel"; public ThermalResultFactory() { - super(ThermalHouseResult.class, CylindricalStorageResult.class); + super( + ThermalHouseResult.class, + CylindricalStorageResult.class, + DomesticHotWaterStorageResult.class); } /** @@ -38,7 +42,11 @@ public ThermalResultFactory() { * @param dateTimeFormatter parse date time strings */ public ThermalResultFactory(DateTimeFormatter dateTimeFormatter) { - super(dateTimeFormatter, ThermalHouseResult.class, CylindricalStorageResult.class); + super( + dateTimeFormatter, + ThermalHouseResult.class, + CylindricalStorageResult.class, + DomesticHotWaterStorageResult.class); } @Override @@ -49,6 +57,8 @@ protected List> getFields(Class entityClass) { minConstructorParams = newSet(TIME, INPUT_MODEL, Q_DOT, INDOOR_TEMPERATURE); } else if (entityClass.equals(CylindricalStorageResult.class)) { minConstructorParams = newSet(TIME, INPUT_MODEL, Q_DOT, ENERGY, FILL_LEVEL); + } else if (entityClass.equals(DomesticHotWaterStorageResult.class)) { + minConstructorParams = newSet(TIME, INPUT_MODEL, Q_DOT, ENERGY, FILL_LEVEL); } return List.of(minConstructorParams); @@ -75,6 +85,14 @@ protected ThermalUnitResult buildModel(EntityData data) { return new CylindricalStorageResult( zdtTime, inputModelUuid, energyQuantity, qDotQuantity, fillLevelQuantity); + } else if (clazz.equals(DomesticHotWaterStorageResult.class)) { + ComparableQuantity energyQuantity = + data.getQuantity(ENERGY, StandardUnits.ENERGY_RESULT); + ComparableQuantity fillLevelQuantity = + data.getQuantity(FILL_LEVEL, StandardUnits.FILL_LEVEL); + + return new DomesticHotWaterStorageResult( + zdtTime, inputModelUuid, energyQuantity, qDotQuantity, fillLevelQuantity); } else { throw new FactoryException("Cannot process " + clazz.getSimpleName() + ".class."); } diff --git a/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java index 18c6a723f..6986361ee 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java @@ -18,6 +18,7 @@ import edu.ie3.datamodel.models.input.system.*; import edu.ie3.datamodel.models.input.system.type.*; import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput; +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput; import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput; import java.util.List; @@ -60,6 +61,8 @@ public class InputEntityProcessor extends EntityProcessor { /* -- ThermalUnitInput */ ThermalHouseInput.class, CylindricalStorageInput.class, + DomesticHotWaterStorageInput.class, + /* - GraphicInput */ NodeGraphicInput.class, LineGraphicInput.class, diff --git a/src/main/java/edu/ie3/datamodel/io/processor/result/ResultEntityProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/result/ResultEntityProcessor.java index 0e347aa5f..224b75850 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/result/ResultEntityProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/result/ResultEntityProcessor.java @@ -18,6 +18,7 @@ import edu.ie3.datamodel.models.result.connector.Transformer3WResult; import edu.ie3.datamodel.models.result.system.*; import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult; +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult; import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.*; @@ -58,6 +59,7 @@ public class ResultEntityProcessor extends EntityProcessor { NodeResult.class, ThermalHouseResult.class, CylindricalStorageResult.class, + DomesticHotWaterStorageResult.class, EmResult.class, FlexOptionsResult.class, CongestionResult.class); diff --git a/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java b/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java index 72ab4d8b7..d1889c4bd 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java @@ -18,6 +18,7 @@ import edu.ie3.datamodel.models.result.connector.Transformer3WResult; import edu.ie3.datamodel.models.result.system.*; import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult; +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult; import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult; import edu.ie3.datamodel.utils.Try; import java.time.format.DateTimeFormatter; @@ -95,6 +96,7 @@ public void validate() throws ValidationException { List.of( validate(ThermalHouseResult.class, dataSource, thermalResultFactory), validate(CylindricalStorageResult.class, dataSource, thermalResultFactory), + validate(DomesticHotWaterStorageResult.class, dataSource, thermalResultFactory), validate(SwitchResult.class, dataSource, switchResultFactory), validate(NodeResult.class, dataSource, nodeResultFactory), validate(LineResult.class, dataSource, connectorResultFactory), @@ -336,6 +338,21 @@ public Set getCylindricalStorageResult() throws Source return getResultEntities(CylindricalStorageResult.class, thermalResultFactory); } + /** + * Returns a unique set of {@link DomesticHotWaterStorageResult} instances. + * + *

This set has to be unique in the sense of object uniqueness but also in the sense of {@link + * java.util.UUID} uniqueness of the provided {@link DomesticHotWaterStorageResult} which has to + * be checked manually, as {@link DomesticHotWaterStorageResult#equals(Object)} is NOT restricted + * by the uuid of {@link DomesticHotWaterStorageResult}. + * + * @return a set of object and uuid unique {@link DomesticHotWaterStorageResult} entities + */ + public Set getDomesticHotWaterStorageResult() + throws SourceException { + return getResultEntities(DomesticHotWaterStorageResult.class, thermalResultFactory); + } + /** * Returns a unique set of {@link ThermalHouseResult} instances. * diff --git a/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java b/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java index f3334600d..f8d73a0a7 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java @@ -9,11 +9,9 @@ import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.input.*; import edu.ie3.datamodel.models.input.OperatorInput; -import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput; -import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; -import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput; -import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput; +import edu.ie3.datamodel.models.input.thermal.*; import edu.ie3.datamodel.utils.Try; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -34,6 +32,7 @@ public class ThermalSource extends AssetEntitySource { // factories private final ThermalBusInputFactory thermalBusInputFactory; private final CylindricalStorageInputFactory cylindricalStorageInputFactory; + private final DomesticHotWaterStorageInputFactory domesticHotWaterStorageInputFactory; private final ThermalHouseInputFactory thermalHouseInputFactory; // enriching function @@ -51,6 +50,7 @@ public ThermalSource(TypeSource typeSource, DataSource dataSource) { this.thermalBusInputFactory = new ThermalBusInputFactory(); this.cylindricalStorageInputFactory = new CylindricalStorageInputFactory(); + this.domesticHotWaterStorageInputFactory = new DomesticHotWaterStorageInputFactory(); this.thermalHouseInputFactory = new ThermalHouseInputFactory(); } @@ -60,6 +60,10 @@ public void validate() throws ValidationException { Stream.of( validate(ThermalBusInput.class, dataSource, thermalBusInputFactory), validate(CylindricalStorageInput.class, dataSource, cylindricalStorageInputFactory), + validate( + DomesticHotWaterStorageInput.class, + dataSource, + domesticHotWaterStorageInputFactory), validate(ThermalHouseInput.class, dataSource, thermalHouseInputFactory)), "Validation") .transformF(FailedValidationException::new) @@ -121,7 +125,9 @@ public Map getThermalBuses(Map opera * @return a map of UUID to object- and uuid-unique {@link ThermalStorageInput} entities */ public Map getThermalStorages() throws SourceException { - return getCylindricalStorages().stream().collect(toMap()); + return Stream.of(getCylindricalStorages(), getDomesticHotWaterStorages()) + .flatMap(Collection::stream) + .collect(toMap()); } /** @@ -146,7 +152,11 @@ public Map getThermalStorages() throws SourceExceptio public Map getThermalStorages( Map operators, Map thermalBuses) throws SourceException { - return getCylindricalStorages(operators, thermalBuses).stream().collect(toMap()); + return Stream.of( + getCylindricalStorages(operators, thermalBuses), + getDomesticHotWaterStorages(operators, thermalBuses)) + .flatMap(Collection::stream) + .collect(toMap()); } /** @@ -214,6 +224,23 @@ public Set getCylindricalStorages() throws SourceExcept return getCylindricalStorages(operators, thermalBuses); } + /** + * Returns a unique set of {@link DomesticHotWaterStorageInput} instances. + * + *

This set has to be unique in the sense of object uniqueness but also in the sense of {@link + * java.util.UUID} uniqueness of the provided {@link DomesticHotWaterStorageInput} which has to be + * checked manually, as {@link DomesticHotWaterStorageInput#equals(Object)} is NOT restricted on + * the uuid of {@link DomesticHotWaterStorageInput}. + * + * @return a set of object- and uuid-unique {@link DomesticHotWaterStorageInput} entities + */ + public Set getDomesticHotWaterStorages() throws SourceException { + Map operators = typeSource.getOperators(); + Map thermalBuses = getThermalBuses(); + + return getDomesticHotWaterStorages(operators, thermalBuses); + } + /** * Returns a set of {@link CylindricalStorageInput} instances. * @@ -244,4 +271,35 @@ public Set getCylindricalStorages( data -> thermalUnitEnricher.apply(data, operators, thermalBuses)) .collect(toSet()); } + + /** + * Returns a set of {@link DomesticHotWaterStorageInput} instances. + * + *

This set has to be unique in the sense of object uniqueness but also in the sense of {@link + * java.util.UUID} uniqueness of the provided {@link DomesticHotWaterStorageInput} which has to be + * checked manually, as {@link DomesticHotWaterStorageInput#equals(Object)} is NOT restricted on + * the uuid of {@link DomesticHotWaterStorageInput}. + * + *

In contrast to {@link #getDomesticHotWaterStorages()} this interface provides the ability to + * pass in an already existing set of {@link OperatorInput} entities, the {@link + * DomesticHotWaterStorageInput} instances depend on. Doing so, already loaded nodes can be + * recycled to improve performance and prevent unnecessary loading operations. + * + *

If something fails during the creation process it's up to the concrete implementation of an + * empty set or a set with all entities that has been able to be build is returned. + * + * @param operators a set of object- and uuid-unique {@link OperatorInput} entities + * @param thermalBuses a set of object- and uuid-unique {@link ThermalBusInput} entities + * @return a set of object- and uuid-unique {@link DomesticHotWaterStorageInput} entities + */ + public Set getDomesticHotWaterStorages( + Map operators, Map thermalBuses) + throws SourceException { + return getEntities( + DomesticHotWaterStorageInput.class, + dataSource, + domesticHotWaterStorageInputFactory, + data -> thermalUnitEnricher.apply(data, operators, thermalBuses)) + .collect(toSet()); + } } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvThermalGridSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvThermalGridSource.java index 377f54508..03e647c55 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvThermalGridSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvThermalGridSource.java @@ -14,10 +14,7 @@ import edu.ie3.datamodel.io.source.TypeSource; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.models.input.container.ThermalGrid; -import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; -import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput; -import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput; -import edu.ie3.datamodel.models.input.thermal.ThermalUnitInput; +import edu.ie3.datamodel.models.input.thermal.*; import edu.ie3.datamodel.utils.Try; import java.nio.file.Path; import java.util.*; @@ -66,16 +63,17 @@ public static List read( Map operators = typeSource.getOperators(); Map buses = thermalSource.getThermalBuses(); - // calling Map.values() because we want to map the inputs to their thermal bus Try, SourceException> houses = Try.of( () -> thermalSource.getThermalHouses(operators, buses).values(), SourceException.class); - Try, SourceException> storages = + Try, SourceException> heatStorages = + Try.of(() -> thermalSource.getCylindricalStorages(operators, buses), SourceException.class); + Try, SourceException> waterStorages = Try.of( - () -> thermalSource.getThermalStorages(operators, buses).values(), + () -> thermalSource.getDomesticHotWaterStorages(operators, buses), SourceException.class); - List exceptions = Try.getExceptions(houses, storages); + List exceptions = Try.getExceptions(houses, heatStorages, waterStorages); if (!exceptions.isEmpty()) { throw new SourceException( @@ -87,16 +85,20 @@ public static List read( Map> houseInputs = houses.getOrThrow().stream() .collect(Collectors.groupingBy(ThermalUnitInput::getThermalBus, Collectors.toSet())); - Map> storageInputs = - storages.getOrThrow().stream() + Map> heatStorageInputs = + heatStorages.getOrThrow().stream() + .collect(Collectors.groupingBy(ThermalUnitInput::getThermalBus, Collectors.toSet())); + Map> waterStorageInputs = + waterStorages.getOrThrow().stream() .collect(Collectors.groupingBy(ThermalUnitInput::getThermalBus, Collectors.toSet())); return buses.values().stream() .map( bus -> { Set h = houseInputs.getOrDefault(bus, emptySet()); - Set s = storageInputs.getOrDefault(bus, emptySet()); - return new ThermalGrid(bus, h, s); + Set hs = heatStorageInputs.getOrDefault(bus, emptySet()); + Set ws = waterStorageInputs.getOrDefault(bus, emptySet()); + return new ThermalGrid(bus, h, hs, ws); }) .toList(); } diff --git a/src/main/java/edu/ie3/datamodel/models/input/container/ThermalGrid.java b/src/main/java/edu/ie3/datamodel/models/input/container/ThermalGrid.java index b3616bc70..0a46b9ce2 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/container/ThermalGrid.java +++ b/src/main/java/edu/ie3/datamodel/models/input/container/ThermalGrid.java @@ -18,21 +18,31 @@ * edu.ie3.datamodel.models.input.thermal.ThermalUnitInput}s */ public record ThermalGrid( - ThermalBusInput bus, Set houses, Set storages) + ThermalBusInput bus, + Set houses, + Set heatStorages, + Set domesticHotWaterStorages) implements InputContainer { public ThermalGrid( ThermalBusInput bus, Collection houses, - Collection storages) { - this(bus, new HashSet<>(houses), new HashSet<>(storages)); + Collection heatStorages, + Collection domesticHotWaterStorages) { + this( + bus, + new HashSet<>(houses), + new HashSet<>(heatStorages), + new HashSet<>(domesticHotWaterStorages)); } @Override public List allEntitiesAsList() { - List ret = new ArrayList<>(houses.size() + storages.size() + 1); + List ret = + new ArrayList<>(houses.size() + heatStorages.size() + domesticHotWaterStorages.size() + 1); ret.add(bus); ret.addAll(houses); - ret.addAll(storages); + ret.addAll(heatStorages); + ret.addAll(domesticHotWaterStorages); return ret; } @@ -48,8 +58,10 @@ public String toString() { + bus + ", #houses=" + houses.size() - + ", #storages=" - + storages.size() + + ", #heatStorages=" + + heatStorages.size() + + ", #domesticHotWaterStorages=" + + domesticHotWaterStorages.size() + '}'; } @@ -63,7 +75,8 @@ public String toString() { public static class ThermalGridCopyBuilder implements InputContainerCopyBuilder { private ThermalBusInput bus; private Set houses; - private Set storages; + private Set heatStorages; + private Set domesticHotWaterStorages; /** * Constructor for {@link ThermalGridCopyBuilder} @@ -73,7 +86,8 @@ public static class ThermalGridCopyBuilder implements InputContainerCopyBuilder< protected ThermalGridCopyBuilder(ThermalGrid thermalGrid) { this.bus = thermalGrid.bus(); this.houses = thermalGrid.houses(); - this.storages = thermalGrid.storages(); + this.heatStorages = thermalGrid.heatStorages(); + this.domesticHotWaterStorages = thermalGrid.domesticHotWaterStorages(); } /** @@ -101,11 +115,23 @@ public ThermalGridCopyBuilder houses(Set houses) { /** * Method to alter {@link ThermalStorageInput} * - * @param storages altered thermal storages + * @param heatStorages altered thermal storages * @return this instance of {@link ThermalGridCopyBuilder} */ - public ThermalGridCopyBuilder storages(Set storages) { - this.storages = storages; + public ThermalGridCopyBuilder heatStorages(Set heatStorages) { + this.heatStorages = heatStorages; + return this; + } + + /** + * Method to alter {@link ThermalStorageInput} + * + * @param domesticHotWaterStorages altered thermal storages + * @return this instance of {@link ThermalGridCopyBuilder} + */ + public ThermalGridCopyBuilder domesticHotWaterStorages( + Set domesticHotWaterStorages) { + this.domesticHotWaterStorages = domesticHotWaterStorages; return this; } @@ -114,8 +140,12 @@ public ThermalGridCopyBuilder scale(Double factor) { houses.stream() .map(house -> house.copy().scale(factor).build()) .collect(Collectors.toSet())); - storages( - storages.stream() + heatStorages( + heatStorages.stream() + .map(storage -> storage.copy().scale(factor).build()) + .collect(Collectors.toSet())); + domesticHotWaterStorages( + domesticHotWaterStorages.stream() .map(storage -> storage.copy().scale(factor).build()) .collect(Collectors.toSet())); return this; @@ -123,7 +153,7 @@ public ThermalGridCopyBuilder scale(Double factor) { @Override public ThermalGrid build() { - return new ThermalGrid(bus, houses, storages); + return new ThermalGrid(bus, houses, heatStorages, domesticHotWaterStorages); } } } diff --git a/src/main/java/edu/ie3/datamodel/models/input/thermal/AbstractStorageInput.java b/src/main/java/edu/ie3/datamodel/models/input/thermal/AbstractStorageInput.java new file mode 100644 index 000000000..a7d495c45 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/thermal/AbstractStorageInput.java @@ -0,0 +1,230 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.thermal; + +import edu.ie3.datamodel.models.OperationTime; +import edu.ie3.datamodel.models.StandardUnits; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.util.quantities.interfaces.SpecificHeatCapacity; +import java.util.Objects; +import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Temperature; +import javax.measure.quantity.Volume; +import tech.units.indriya.ComparableQuantity; + +/** Thermal storage with cylindrical shape */ +public abstract class AbstractStorageInput extends ThermalStorageInput { + /** Available storage volume (typically in m³) */ + private final ComparableQuantity storageVolumeLvl; + /** Temperature of the inlet (typically in C) */ + private final ComparableQuantity inletTemp; + /** Temperature of the outlet (typically in C) */ + private final ComparableQuantity returnTemp; + /** Specific heat capacity of the storage medium (typically in kWh/K*m³) */ + private final ComparableQuantity c; + /** Maximum permissible thermal power (typically in kW) */ + private final ComparableQuantity pThermalMax; + + /** + * @param uuid Unique identifier of a cylindrical storage + * @param id Identifier of the thermal unit + * @param operator operator of the asset + * @param operationTime operation time of the asset + * @param bus Thermal bus, a thermal unit is connected to + * @param storageVolumeLvl Available storage volume + * @param inletTemp Temperature of the inlet + * @param returnTemp Temperature of the outlet + * @param c Specific heat capacity of the storage medium + * @param pThermalMax Maximum thermal power of the storage + */ + public AbstractStorageInput( + UUID uuid, + String id, + OperatorInput operator, + OperationTime operationTime, + ThermalBusInput bus, + ComparableQuantity storageVolumeLvl, + ComparableQuantity inletTemp, + ComparableQuantity returnTemp, + ComparableQuantity c, + ComparableQuantity pThermalMax) { + super(uuid, id, operator, operationTime, bus); + this.storageVolumeLvl = storageVolumeLvl.to(StandardUnits.VOLUME); + this.inletTemp = inletTemp.to(StandardUnits.TEMPERATURE); + this.returnTemp = returnTemp.to(StandardUnits.TEMPERATURE); + this.c = c.to(StandardUnits.SPECIFIC_HEAT_CAPACITY); + this.pThermalMax = pThermalMax.to(StandardUnits.ACTIVE_POWER_IN); + } + + /** + * @param uuid Unique identifier of a cylindrical storage + * @param id Identifier of the thermal unit + * @param bus Thermal bus, a thermal unit is connected to + * @param storageVolumeLvl Available storage volume + * @param inletTemp Temperature of the inlet + * @param returnTemp Temperature of the outlet + * @param c Specific heat capacity of the storage medium + * @param pThermalMax Maximum thermal power of the storage + */ + public AbstractStorageInput( + UUID uuid, + String id, + ThermalBusInput bus, + ComparableQuantity storageVolumeLvl, + ComparableQuantity inletTemp, + ComparableQuantity returnTemp, + ComparableQuantity c, + ComparableQuantity pThermalMax) { + super(uuid, id, bus); + this.storageVolumeLvl = storageVolumeLvl.to(StandardUnits.VOLUME); + this.inletTemp = inletTemp.to(StandardUnits.TEMPERATURE); + this.returnTemp = returnTemp.to(StandardUnits.TEMPERATURE); + this.c = c.to(StandardUnits.SPECIFIC_HEAT_CAPACITY); + this.pThermalMax = pThermalMax.to(StandardUnits.ACTIVE_POWER_IN); + } + + public ComparableQuantity getStorageVolumeLvl() { + return storageVolumeLvl; + } + + public ComparableQuantity getInletTemp() { + return inletTemp; + } + + public ComparableQuantity getReturnTemp() { + return returnTemp; + } + + public ComparableQuantity getC() { + return c; + } + + public ComparableQuantity getpThermalMax() { + return pThermalMax; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AbstractStorageInput that)) return false; + if (!super.equals(o)) return false; + return storageVolumeLvl.equals(that.storageVolumeLvl) + && inletTemp.equals(that.inletTemp) + && returnTemp.equals(that.returnTemp) + && c.equals(that.c) + && pThermalMax.equals(that.getpThermalMax()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), storageVolumeLvl, inletTemp, returnTemp, c, pThermalMax); + } + + @Override + public String toString() { + return "CylindricalStorageInput{" + + "uuid=" + + getUuid() + + ", id=" + + getId() + + ", operator=" + + getOperator().getUuid() + + ", operationTime=" + + getOperationTime() + + ", bus=" + + getThermalBus().getUuid() + + ", storageVolumeLvl=" + + storageVolumeLvl + + ", inletTemp=" + + inletTemp + + ", returnTemp=" + + returnTemp + + ", c=" + + c + + ", pThermalMax=" + + pThermalMax + + '}'; + } + + /** + * A builder pattern based approach to create copies of {@link AbstractStorageInput} entities with + * altered field values. For detailed field descriptions refer to java docs of {@link + * AbstractStorageInput} + */ + protected abstract static class AbstractStorageInputCopyBuilder< + B extends AbstractStorageInputCopyBuilder> + extends ThermalStorageInputCopyBuilder { + + private ComparableQuantity storageVolumeLvl; + private ComparableQuantity inletTemp; + private ComparableQuantity returnTemp; + private ComparableQuantity c; + private ComparableQuantity pThermalMax; + + protected AbstractStorageInputCopyBuilder(AbstractStorageInput entity) { + super(entity); + + this.storageVolumeLvl = entity.getStorageVolumeLvl(); + this.inletTemp = entity.getInletTemp(); + this.returnTemp = entity.getReturnTemp(); + this.c = entity.getC(); + this.pThermalMax = entity.getpThermalMax(); + } + + public B storageVolumeLvl(ComparableQuantity storageVolumeLvl) { + this.storageVolumeLvl = storageVolumeLvl; + return thisInstance(); + } + + public B inletTemp(ComparableQuantity inletTemp) { + this.inletTemp = inletTemp; + return thisInstance(); + } + + public B returnTemp(ComparableQuantity returnTemp) { + this.returnTemp = returnTemp; + return thisInstance(); + } + + public B c(ComparableQuantity c) { + this.c = c; + return thisInstance(); + } + + public B pThermalMax(ComparableQuantity pThermalMax) { + this.pThermalMax = pThermalMax; + return thisInstance(); + } + + @Override + public B scale(Double factor) { + storageVolumeLvl(storageVolumeLvl.multiply(factor)); + pThermalMax(pThermalMax.multiply(factor)); + return thisInstance(); + } + + public ComparableQuantity getStorageVolumeLvl() { + return storageVolumeLvl; + } + + public ComparableQuantity getInletTemp() { + return inletTemp; + } + + public ComparableQuantity getReturnTemp() { + return returnTemp; + } + + public ComparableQuantity getC() { + return c; + } + + public ComparableQuantity getpThermalMax() { + return pThermalMax; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/thermal/CylindricalStorageInput.java b/src/main/java/edu/ie3/datamodel/models/input/thermal/CylindricalStorageInput.java index 443f708bc..9e43ef04b 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/thermal/CylindricalStorageInput.java +++ b/src/main/java/edu/ie3/datamodel/models/input/thermal/CylindricalStorageInput.java @@ -6,10 +6,8 @@ package edu.ie3.datamodel.models.input.thermal; import edu.ie3.datamodel.models.OperationTime; -import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.util.quantities.interfaces.SpecificHeatCapacity; -import java.util.Objects; import java.util.UUID; import javax.measure.quantity.Power; import javax.measure.quantity.Temperature; @@ -17,18 +15,7 @@ import tech.units.indriya.ComparableQuantity; /** Thermal storage with cylindrical shape */ -public class CylindricalStorageInput extends ThermalStorageInput { - /** Available storage volume (typically in m³) */ - private final ComparableQuantity storageVolumeLvl; - /** Temperature of the inlet (typically in C) */ - private final ComparableQuantity inletTemp; - /** Temperature of the outlet (typically in C) */ - private final ComparableQuantity returnTemp; - /** Specific heat capacity of the storage medium (typically in kWh/K*m³) */ - private final ComparableQuantity c; - /** Maximum permissible thermal power (typically in kW) */ - private final ComparableQuantity pThermalMax; - +public class CylindricalStorageInput extends AbstractStorageInput { /** * @param uuid Unique identifier of a cylindrical storage * @param id Identifier of the thermal unit @@ -52,12 +39,17 @@ public CylindricalStorageInput( ComparableQuantity returnTemp, ComparableQuantity c, ComparableQuantity pThermalMax) { - super(uuid, id, operator, operationTime, bus); - this.storageVolumeLvl = storageVolumeLvl.to(StandardUnits.VOLUME); - this.inletTemp = inletTemp.to(StandardUnits.TEMPERATURE); - this.returnTemp = returnTemp.to(StandardUnits.TEMPERATURE); - this.c = c.to(StandardUnits.SPECIFIC_HEAT_CAPACITY); - this.pThermalMax = pThermalMax.to(StandardUnits.ACTIVE_POWER_IN); + super( + uuid, + id, + operator, + operationTime, + bus, + storageVolumeLvl, + inletTemp, + returnTemp, + c, + pThermalMax); } /** @@ -79,32 +71,7 @@ public CylindricalStorageInput( ComparableQuantity returnTemp, ComparableQuantity c, ComparableQuantity pThermalMax) { - super(uuid, id, bus); - this.storageVolumeLvl = storageVolumeLvl.to(StandardUnits.VOLUME); - this.inletTemp = inletTemp.to(StandardUnits.TEMPERATURE); - this.returnTemp = returnTemp.to(StandardUnits.TEMPERATURE); - this.c = c.to(StandardUnits.SPECIFIC_HEAT_CAPACITY); - this.pThermalMax = pThermalMax.to(StandardUnits.ACTIVE_POWER_IN); - } - - public ComparableQuantity getStorageVolumeLvl() { - return storageVolumeLvl; - } - - public ComparableQuantity getInletTemp() { - return inletTemp; - } - - public ComparableQuantity getReturnTemp() { - return returnTemp; - } - - public ComparableQuantity getC() { - return c; - } - - public ComparableQuantity getpThermalMax() { - return pThermalMax; + super(uuid, id, bus, storageVolumeLvl, inletTemp, returnTemp, c, pThermalMax); } @Override @@ -112,23 +79,6 @@ public CylindricalStorageInputCopyBuilder copy() { return new CylindricalStorageInputCopyBuilder(this); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CylindricalStorageInput that)) return false; - if (!super.equals(o)) return false; - return storageVolumeLvl.equals(that.storageVolumeLvl) - && inletTemp.equals(that.inletTemp) - && returnTemp.equals(that.returnTemp) - && c.equals(that.c) - && pThermalMax.equals(that.getpThermalMax()); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), storageVolumeLvl, inletTemp, returnTemp, c, pThermalMax); - } - @Override public String toString() { return "CylindricalStorageInput{" @@ -143,15 +93,15 @@ public String toString() { + ", bus=" + getThermalBus().getUuid() + ", storageVolumeLvl=" - + storageVolumeLvl + + getStorageVolumeLvl() + ", inletTemp=" - + inletTemp + + getInletTemp() + ", returnTemp=" - + returnTemp + + getReturnTemp() + ", c=" - + c + + getC() + ", pThermalMax=" - + pThermalMax + + getpThermalMax() + '}'; } @@ -161,55 +111,10 @@ public String toString() { * CylindricalStorageInput} */ public static class CylindricalStorageInputCopyBuilder - extends ThermalStorageInputCopyBuilder { + extends AbstractStorageInputCopyBuilder { - private ComparableQuantity storageVolumeLvl; - private ComparableQuantity inletTemp; - private ComparableQuantity returnTemp; - private ComparableQuantity c; - private ComparableQuantity pThermalMax; - - private CylindricalStorageInputCopyBuilder(CylindricalStorageInput entity) { + protected CylindricalStorageInputCopyBuilder(CylindricalStorageInput entity) { super(entity); - this.storageVolumeLvl = entity.getStorageVolumeLvl(); - this.inletTemp = entity.getInletTemp(); - this.returnTemp = entity.getReturnTemp(); - this.c = entity.getC(); - this.pThermalMax = entity.getpThermalMax(); - } - - public CylindricalStorageInputCopyBuilder storageVolumeLvl( - ComparableQuantity storageVolumeLvl) { - this.storageVolumeLvl = storageVolumeLvl; - return this; - } - - public CylindricalStorageInputCopyBuilder inletTemp(ComparableQuantity inletTemp) { - this.inletTemp = inletTemp; - return this; - } - - public CylindricalStorageInputCopyBuilder returnTemp( - ComparableQuantity returnTemp) { - this.returnTemp = returnTemp; - return this; - } - - public CylindricalStorageInputCopyBuilder c(ComparableQuantity c) { - this.c = c; - return this; - } - - public CylindricalStorageInputCopyBuilder pThermalMax(ComparableQuantity pThermalMax) { - this.pThermalMax = pThermalMax; - return this; - } - - @Override - public CylindricalStorageInputCopyBuilder scale(Double factor) { - storageVolumeLvl(storageVolumeLvl.multiply(factor)); - pThermalMax(pThermalMax.multiply(factor)); - return this; } @Override @@ -220,11 +125,11 @@ public CylindricalStorageInput build() { getOperator(), getOperationTime(), getThermalBus(), - storageVolumeLvl, - inletTemp, - returnTemp, - c, - pThermalMax); + getStorageVolumeLvl(), + getInletTemp(), + getReturnTemp(), + getC(), + getpThermalMax()); } @Override diff --git a/src/main/java/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInput.java b/src/main/java/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInput.java new file mode 100644 index 000000000..b26af2c79 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInput.java @@ -0,0 +1,139 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.thermal; + +import edu.ie3.datamodel.models.OperationTime; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.util.quantities.interfaces.SpecificHeatCapacity; +import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Temperature; +import javax.measure.quantity.Volume; +import tech.units.indriya.ComparableQuantity; + +public class DomesticHotWaterStorageInput extends AbstractStorageInput { + + /** + * Constructor for DomesticHotWaterStorageInput + * + * @param uuid Unique identifier of a domestic hot water storage + * @param id Identifier of the thermal unit + * @param operator operator of the asset + * @param operationTime operation time of the asset + * @param bus Thermal bus, a thermal unit is connected to + * @param storageVolumeLvl Available storage volume + * @param inletTemp Temperature of the inlet + * @param returnTemp Temperature of the outlet + * @param c Specific heat capacity of the storage medium + * @param pThermalMax Maximum thermal power of the storage + */ + public DomesticHotWaterStorageInput( + UUID uuid, + String id, + OperatorInput operator, + OperationTime operationTime, + ThermalBusInput bus, + ComparableQuantity storageVolumeLvl, + ComparableQuantity inletTemp, + ComparableQuantity returnTemp, + ComparableQuantity c, + ComparableQuantity pThermalMax) { + super( + uuid, + id, + operator, + operationTime, + bus, + storageVolumeLvl, + inletTemp, + returnTemp, + c, + pThermalMax); + } + + /** + * Alternative constructor for DomesticHotWaterStorageInput + * + * @param uuid Unique identifier of a domestic hot water storage + * @param id Identifier of the thermal unit + * @param bus Thermal bus, a thermal unit is connected to + * @param storageVolumeLvl Available storage volume + * @param inletTemp Temperature of the inlet + * @param returnTemp Temperature of the outlet + * @param c Specific heat capacity of the storage medium + * @param pThermalMax Maximum thermal power of the storage + */ + public DomesticHotWaterStorageInput( + UUID uuid, + String id, + ThermalBusInput bus, + ComparableQuantity storageVolumeLvl, + ComparableQuantity inletTemp, + ComparableQuantity returnTemp, + ComparableQuantity c, + ComparableQuantity pThermalMax) { + super(uuid, id, bus, storageVolumeLvl, inletTemp, returnTemp, c, pThermalMax); + } + + @Override + public DomesticHotWaterStorageInputCopyBuilder copy() { + return new DomesticHotWaterStorageInputCopyBuilder(this); + } + + @Override + public String toString() { + return "DomesticHotWaterStorageInput{" + + "uuid=" + + getUuid() + + ", id=" + + getId() + + ", operator=" + + getOperator().getUuid() + + ", operationTime=" + + getOperationTime() + + ", bus=" + + getThermalBus().getUuid() + + ", storageVolumeLvl=" + + getStorageVolumeLvl() + + ", inletTemp=" + + getInletTemp() + + ", returnTemp=" + + getReturnTemp() + + ", c=" + + getC() + + ", pThermalMax=" + + getpThermalMax() + + '}'; + } + + public static class DomesticHotWaterStorageInputCopyBuilder + extends AbstractStorageInputCopyBuilder { + + protected DomesticHotWaterStorageInputCopyBuilder(DomesticHotWaterStorageInput entity) { + super(entity); + } + + @Override + public DomesticHotWaterStorageInput build() { + return new DomesticHotWaterStorageInput( + getUuid(), + getId(), + getOperator(), + getOperationTime(), + getThermalBus(), + getStorageVolumeLvl(), + getInletTemp(), + getReturnTemp(), + getC(), + getpThermalMax()); + } + + @Override + protected DomesticHotWaterStorageInputCopyBuilder thisInstance() { + return this; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/result/thermal/AbstractThermalStorageResult.java b/src/main/java/edu/ie3/datamodel/models/result/thermal/AbstractThermalStorageResult.java new file mode 100644 index 000000000..293ab29bf --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/result/thermal/AbstractThermalStorageResult.java @@ -0,0 +1,79 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.result.thermal; + +import edu.ie3.datamodel.models.StandardUnits; +import java.time.ZonedDateTime; +import java.util.Objects; +import java.util.UUID; +import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.Energy; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; + +/** Abstract class representing the common results of different types of thermal storages */ +public abstract class AbstractThermalStorageResult extends ThermalStorageResult { + /** Fill level of the storage */ + private ComparableQuantity fillLevel; + + /** + * Constructs the result with + * + * @param time date and time when the result is produced + * @param inputModel uuid of the input model that produces the result + * @param energy Currently stored energy + * @param qDot Heat power flowing into (> 0) or coming from (< 0) the storage + * @param fillLevel Fill level of the storage + */ + protected AbstractThermalStorageResult( + ZonedDateTime time, + UUID inputModel, + ComparableQuantity energy, + ComparableQuantity qDot, + ComparableQuantity fillLevel) { + super(time, inputModel, energy, qDot); + this.fillLevel = fillLevel.to(StandardUnits.FILL_LEVEL); + } + + public ComparableQuantity getFillLevel() { + return fillLevel; + } + + public void setFillLevel(ComparableQuantity fillLevel) { + this.fillLevel = fillLevel.to(StandardUnits.FILL_LEVEL); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + AbstractThermalStorageResult that = (AbstractThermalStorageResult) o; + return fillLevel.equals(that.fillLevel); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), fillLevel); + } + + @Override + public String toString() { + return getClass().getSimpleName() + + "{" + + "time=" + + getTime() + + ", inputModel=" + + getInputModel() + + ", qDot=" + + getqDot() + + ", energy=" + + getEnergy() + + ", fillLevel=" + + fillLevel + + '}'; + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/result/thermal/CylindricalStorageResult.java b/src/main/java/edu/ie3/datamodel/models/result/thermal/CylindricalStorageResult.java index 40ab5bc1f..eeadc0bb8 100644 --- a/src/main/java/edu/ie3/datamodel/models/result/thermal/CylindricalStorageResult.java +++ b/src/main/java/edu/ie3/datamodel/models/result/thermal/CylindricalStorageResult.java @@ -5,75 +5,22 @@ */ package edu.ie3.datamodel.models.result.thermal; -import edu.ie3.datamodel.models.StandardUnits; -import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput; import java.time.ZonedDateTime; -import java.util.Objects; import java.util.UUID; import javax.measure.quantity.Dimensionless; import javax.measure.quantity.Energy; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; -/** Respresents the results of {@link CylindricalStorageInput} */ -public class CylindricalStorageResult extends ThermalStorageResult { - /** Fill level of the storage */ - private ComparableQuantity fillLevel; +/** Represents the results of Cylindrical Storage */ +public class CylindricalStorageResult extends AbstractThermalStorageResult { - /** - * Constructs the result with - * - * @param time date and time when the result is produced - * @param inputModel uuid of the input model that produces the result - * @param energy Currently stored energy - * @param qDot Heat power flowing into (> 0) or coming from (< 0) the storage - * @param fillLevel Fill level of the storage - */ public CylindricalStorageResult( ZonedDateTime time, UUID inputModel, ComparableQuantity energy, ComparableQuantity qDot, ComparableQuantity fillLevel) { - super(time, inputModel, energy, qDot); - this.fillLevel = fillLevel.to(StandardUnits.FILL_LEVEL); - } - - public ComparableQuantity getFillLevel() { - return fillLevel; - } - - public void setFillLevel(ComparableQuantity fillLevel) { - this.fillLevel = fillLevel.to(StandardUnits.FILL_LEVEL); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - CylindricalStorageResult that = (CylindricalStorageResult) o; - return fillLevel.equals(that.fillLevel); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), fillLevel); - } - - @Override - public String toString() { - return "CylindricalStorageResult{" - + "time=" - + getTime() - + ", inputModel=" - + getInputModel() - + ", qDot=" - + getqDot() - + ", energy=" - + getEnergy() - + ", fillLevel=" - + fillLevel - + '}'; + super(time, inputModel, energy, qDot, fillLevel); } } diff --git a/src/main/java/edu/ie3/datamodel/models/result/thermal/DomesticHotWaterStorageResult.java b/src/main/java/edu/ie3/datamodel/models/result/thermal/DomesticHotWaterStorageResult.java new file mode 100644 index 000000000..cf604fe0e --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/result/thermal/DomesticHotWaterStorageResult.java @@ -0,0 +1,26 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.result.thermal; + +import java.time.ZonedDateTime; +import java.util.UUID; +import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.Energy; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; + +/** Represents the results of Domestic Hot Water Storage */ +public class DomesticHotWaterStorageResult extends AbstractThermalStorageResult { + + public DomesticHotWaterStorageResult( + ZonedDateTime time, + UUID inputModel, + ComparableQuantity energy, + ComparableQuantity qDot, + ComparableQuantity fillLevel) { + super(time, inputModel, energy, qDot, fillLevel); + } +} diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java index 3365251b9..72ddf489f 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java @@ -87,8 +87,13 @@ private ThermalValidationUtils() { exceptions.addAll(checkThermalHouse(house)); } - // Validate storages - for (ThermalStorageInput storage : thermalGrid.storages()) { + // Validate heat storages + for (ThermalStorageInput storage : thermalGrid.heatStorages()) { + exceptions.addAll(check(storage)); + } + + // Validate domestic hot water storages + for (ThermalStorageInput storage : thermalGrid.domesticHotWaterStorages()) { exceptions.addAll(check(storage)); } @@ -155,10 +160,13 @@ private ThermalValidationUtils() { List> exceptions = new ArrayList<>(); // Further checks for subclasses - if (CylindricalStorageInput.class.isAssignableFrom(thermalStorageInput.getClass())) { + if (thermalStorageInput.getClass() == CylindricalStorageInput.class) { exceptions.addAll(checkCylindricalStorage((CylindricalStorageInput) thermalStorageInput)); - } else { - logNotImplemented(thermalStorageInput); + } + + if (thermalStorageInput.getClass() == DomesticHotWaterStorageInput.class) { + exceptions.addAll( + checkDomesticHotWaterStorage((DomesticHotWaterStorageInput) thermalStorageInput)); } return exceptions; @@ -290,4 +298,54 @@ private static List> checkCylindricalStorage( return exceptions; } + /** + * Validates a domcesticHotWaterStorageInput if: + * + *

    + *
  • it is not null + *
  • its available storage volume is positive + *
  • its inlet temperature is equal/greater than the outlet temperature + *
  • its specific heat capacity is positive + *
+ * + * @param domesticHotWaterStorageInput DomesticHotWaterStorageInput to validate + * @return a list of try objects either containing an {@link InvalidEntityException} or an empty + * Success + */ + private static List> checkDomesticHotWaterStorage( + DomesticHotWaterStorageInput domesticHotWaterStorageInput) { + Try isNull = + checkNonNull(domesticHotWaterStorageInput, "a domestic hot water storage"); + + if (isNull.isFailure()) { + return List.of(isNull); + } + + List> exceptions = new ArrayList<>(); + + // Check if inlet temperature is higher/equal to outlet temperature + exceptions.add( + Try.ofVoid( + domesticHotWaterStorageInput + .getInletTemp() + .isLessThanOrEqualTo(domesticHotWaterStorageInput.getReturnTemp()), + () -> + new InvalidEntityException( + "Inlet temperature of the domestic hot water storage cannot be lower or equal than outlet temperature", + domesticHotWaterStorageInput))); + + exceptions.add( + Try.ofVoid( + () -> + detectZeroOrNegativeQuantities( + new Quantity[] { + domesticHotWaterStorageInput.getStorageVolumeLvl(), + domesticHotWaterStorageInput.getC(), + domesticHotWaterStorageInput.getpThermalMax() + }, + domesticHotWaterStorageInput), + InvalidEntityException.class)); + + return exceptions; + } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/extractor/ExtractorTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/extractor/ExtractorTest.groovy index 9c4968164..8e8096879 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/extractor/ExtractorTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/extractor/ExtractorTest.groovy @@ -140,6 +140,12 @@ class ExtractorTest extends Specification { tutd.cylindricalStorageInput.thermalBus.operator ] + tutd.domesticHotWaterStorageInput || [ + tutd.domesticHotWaterStorageInput.operator, + tutd.domesticHotWaterStorageInput.thermalBus, + tutd.domesticHotWaterStorageInput.thermalBus.operator + ] + tutd.thermalHouseInput || [ tutd.thermalHouseInput.operator, tutd.thermalHouseInput.thermalBus, diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactoryTest.groovy new file mode 100644 index 000000000..38849415d --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/input/DomesticHotWaterStorageInputFactoryTest.groovy @@ -0,0 +1,62 @@ +/* + * © 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.input + +import edu.ie3.datamodel.exceptions.FactoryException +import edu.ie3.datamodel.models.OperationTime +import edu.ie3.datamodel.models.StandardUnits +import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput +import edu.ie3.datamodel.models.input.thermal.ThermalBusInput +import edu.ie3.datamodel.utils.Try +import edu.ie3.test.helper.FactoryTestHelper +import spock.lang.Specification + +class DomesticHotWaterStorageInputFactoryTest extends Specification implements FactoryTestHelper { + def "A DomesticHotWaterStorageInputFactory should contain exactly the expected class for parsing"() { + given: + def inputFactory = new DomesticHotWaterStorageInputFactory() + def expectedClasses = [DomesticHotWaterStorageInput] + + expect: + inputFactory.supportedClasses == Arrays.asList(expectedClasses.toArray()) + } + + def "A DomesticHotWaterStorageInputFactory should parse a valid DomesticHotWaterStorageInput correctly"() { + given: "a system participant input type factory and model data" + def inputFactory = new DomesticHotWaterStorageInputFactory() + Map parameter = [ + "uuid" : "91ec3bcf-1777-4d38-af67-0bf7c9fa73c7", + "id" : "TestID", + "storagevolumelvl" : "3", + "inlettemp" : "4", + "returntemp" : "5", + "c" : "6", + "pThermalMax" : "7" + ] + def inputClass = DomesticHotWaterStorageInput + def thermalBusInput = Mock(ThermalBusInput) + + when: + Try input = inputFactory.get(new ThermalUnitInputEntityData(parameter, inputClass, thermalBusInput)) + + then: + input.success + input.data.get().getClass() == inputClass + input.data.get().with { + assert uuid == UUID.fromString(parameter["uuid"]) + assert operationTime == OperationTime.notLimited() + assert operator == OperatorInput.NO_OPERATOR_ASSIGNED + assert id == parameter["id"] + assert thermalBus == thermalBusInput + assert storageVolumeLvl == getQuant(parameter["storagevolumelvl"], StandardUnits.VOLUME) + assert inletTemp == getQuant(parameter["inlettemp"], StandardUnits.TEMPERATURE) + assert returnTemp == getQuant(parameter["returntemp"], StandardUnits.TEMPERATURE) + assert c == getQuant(parameter["c"], StandardUnits.SPECIFIC_HEAT_CAPACITY) + assert pThermalMax == getQuant(parameter["pThermalMax"], StandardUnits.ACTIVE_POWER_IN) + } + } +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/result/ThermalResultFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/result/ThermalResultFactoryTest.groovy index 9c64a97ec..fa95f7d6f 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/result/ThermalResultFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/result/ThermalResultFactoryTest.groovy @@ -9,6 +9,7 @@ import edu.ie3.datamodel.exceptions.FactoryException import edu.ie3.datamodel.io.factory.EntityData import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult import edu.ie3.datamodel.models.result.thermal.ThermalUnitResult import edu.ie3.datamodel.utils.Try @@ -23,7 +24,8 @@ class ThermalResultFactoryTest extends Specification implements FactoryTestHelpe def resultFactory = new ThermalResultFactory() def expectedClasses = [ ThermalHouseResult, - CylindricalStorageResult + CylindricalStorageResult, + DomesticHotWaterStorageResult ] expect: @@ -55,6 +57,31 @@ class ThermalResultFactoryTest extends Specification implements FactoryTestHelpe } } + def "A ThermalResultFactory should parse a DomesticHotWaterStorageResult correctly"() { + given: "a thermal result factory and model data" + def resultFactory = new ThermalResultFactory() + Map parameter = [ + "time" : "2020-01-30T17:26:44Z", + "inputModel": "91ec3bcf-1897-4d38-af67-0bf7c9fa73c7", + "qDot" : "2", + "energy" : "3", + "fillLevel" : "20" + ] + when: + Try result = resultFactory.get(new EntityData(parameter, DomesticHotWaterStorageResult)) + + then: + result.success + result.data.get().getClass() == DomesticHotWaterStorageResult + ((DomesticHotWaterStorageResult) result.data.get()).with { + assert time == TIME_UTIL.toZonedDateTime(parameter.get("time")) + assert inputModel == UUID.fromString(parameter.get("inputModel")) + assert qDot == Quantities.getQuantity(Double.parseDouble(parameter.get("qDot")), StandardUnits.HEAT_DEMAND) + assert energy == Quantities.getQuantity(Double.parseDouble(parameter.get("energy")), StandardUnits.ENERGY_RESULT) + assert fillLevel == Quantities.getQuantity(Double.parseDouble(parameter.get("fillLevel")), StandardUnits.FILL_LEVEL) + } + } + def "A ThermalResultFactory should parse a ThermalHouseResult correctly"() { given: "a thermal result factory and model data" def resultFactory = new ThermalResultFactory() diff --git a/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy index 7d63bcfae..cba0a2a29 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy @@ -24,6 +24,7 @@ import edu.ie3.datamodel.models.input.graphics.NodeGraphicInput import edu.ie3.datamodel.models.input.system.* import edu.ie3.datamodel.models.input.system.type.* import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import edu.ie3.datamodel.models.result.CongestionResult @@ -34,6 +35,7 @@ import edu.ie3.datamodel.models.result.connector.Transformer2WResult import edu.ie3.datamodel.models.result.connector.Transformer3WResult import edu.ie3.datamodel.models.result.system.* import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult import edu.ie3.datamodel.models.timeseries.IntValue import edu.ie3.datamodel.models.timeseries.TimeSeries @@ -88,6 +90,7 @@ class ProcessorProviderTest extends Specification implements TimeSeriesTestData /* -- ThermalUnitInput */ ThermalHouseInput, CylindricalStorageInput, + DomesticHotWaterStorageInput, /* - GraphicInput */ NodeGraphicInput, LineGraphicInput, @@ -121,7 +124,8 @@ class ProcessorProviderTest extends Specification implements TimeSeriesTestData NodeResult, CongestionResult, ThermalHouseResult, - CylindricalStorageResult + CylindricalStorageResult, + DomesticHotWaterStorageResult ] // currently known processors diff --git a/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy index 4f5c4a0f1..320dc8db7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy @@ -15,6 +15,7 @@ import edu.ie3.datamodel.models.result.connector.Transformer2WResult import edu.ie3.datamodel.models.result.connector.Transformer3WResult import edu.ie3.datamodel.models.result.system.* import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult +import edu.ie3.datamodel.models.result.thermal.DomesticHotWaterStorageResult import edu.ie3.util.quantities.PowerSystemUnits import spock.lang.Shared import spock.lang.Specification @@ -252,6 +253,30 @@ class ResultEntityProcessorTest extends Specification { validProcessedElement == expectedResults } + def "A ResultEntityProcessor should serialize a DomesticHotWaterStorageResult correctly"() { + given: + def sysPartResProcessor = new ResultEntityProcessor(DomesticHotWaterStorageResult) + + Quantity qDot = Quantities.getQuantity(2, StandardUnits.Q_DOT_RESULT) + Quantity energy = Quantities.getQuantity(3, StandardUnits.ENERGY_RESULT) + Quantity fillLevel = Quantities.getQuantity(20, Units.PERCENT) + + def validResult = new DomesticHotWaterStorageResult(ZonedDateTime.parse("2020-01-30T17:26:44Z"), inputModel, energy, qDot, fillLevel) + + def expectedResults = [ + energy : '3.0', + fillLevel : '20.0', + inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52', + qDot : '2.0', + time : '2020-01-30T17:26:44Z'] + + when: + def validProcessedElement = sysPartResProcessor.handleEntity(validResult) + + then: + validProcessedElement == expectedResults + } + def "A ResultEntityProcessor should throw an EntityProcessorException when it receives an entity result that is not eligible"() { given: @@ -270,7 +295,7 @@ class ResultEntityProcessorTest extends Specification { def "The list of eligible entity classes for a ResultEntityProcessor should be valid"() { given: - int noOfElements = 20 // number of all currently implemented entity results + int noOfElements = 21 // number of all currently implemented entity results expect: ResultEntityProcessor.eligibleEntityClasses.size() == noOfElements diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index 2ee20aa57..08b563aa4 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -31,6 +31,7 @@ import edu.ie3.datamodel.models.input.system.LoadInput import edu.ie3.datamodel.models.input.system.PvInput import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import edu.ie3.datamodel.models.result.system.EmResult @@ -131,6 +132,7 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { new InputEntityProcessor(LineGraphicInput), new InputEntityProcessor(NodeGraphicInput), new InputEntityProcessor(CylindricalStorageInput), + new InputEntityProcessor(DomesticHotWaterStorageInput), new InputEntityProcessor(ThermalHouseInput), new InputEntityProcessor(OperatorInput), new InputEntityProcessor(LineInput), @@ -166,6 +168,7 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { GridTestData.lineGraphicCtoD, GridTestData.nodeGraphicC, ThermalUnitInputTestData.cylindricalStorageInput, + ThermalUnitInputTestData.domesticHotWaterStorageInput, ThermalUnitInputTestData.thermalHouseInput, SystemParticipantTestData.evcsInput, SystemParticipantTestData.loadInput, @@ -185,6 +188,7 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { testBaseFolderPath.resolve("transformer_2_w_input.csv").toFile().exists() testBaseFolderPath.resolve("operator_input.csv").toFile().exists() testBaseFolderPath.resolve("cylindrical_storage_input.csv").toFile().exists() + testBaseFolderPath.resolve("domestic_hot_water_storage_input.csv").toFile().exists() testBaseFolderPath.resolve("line_graphic_input.csv").toFile().exists() testBaseFolderPath.resolve("line_input.csv").toFile().exists() testBaseFolderPath.resolve("operator_input.csv").toFile().exists() diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvThermalGridSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvThermalGridSourceTest.groovy index 57c1b2ec4..ce8b3c7a7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvThermalGridSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvThermalGridSourceTest.groovy @@ -18,7 +18,8 @@ class CsvThermalGridSourceTest extends Specification implements CsvTestDataMeta thermalGrids.get(0).with { def bus = it.bus() assert it.houses().every { it.thermalBus == bus } - assert it.storages().every { it.thermalBus == bus } + assert it.heatStorages().every { it.thermalBus == bus } + assert it.domesticHotWaterStorages().every { it.thermalBus == bus } } } } diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/container/ThermalGridTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/container/ThermalGridTest.groovy index fb8485acb..3dcde3c32 100644 --- a/src/test/groovy/edu/ie3/datamodel/models/input/container/ThermalGridTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/models/input/container/ThermalGridTest.groovy @@ -6,6 +6,7 @@ package edu.ie3.datamodel.models.input.container import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import spock.lang.Specification @@ -19,37 +20,44 @@ class ThermalGridTest extends Specification { Mock(ThermalHouseInput), Mock(ThermalHouseInput) ] - def thermalStorages = [Mock(CylindricalStorageInput)] - def thermalUnits = new ThermalGrid(thermalBus, thermalHouses, thermalStorages) + def heatStorages = [Mock(CylindricalStorageInput)] + def domesticHotWaterStorages = [ + Mock(DomesticHotWaterStorageInput) + ] + def thermalUnits = new ThermalGrid(thermalBus, thermalHouses, heatStorages, domesticHotWaterStorages) when: def actualAllEntities = thermalUnits.allEntitiesAsList() then: - actualAllEntities.size() == 1 + thermalHouses.size() + thermalStorages.size() + actualAllEntities.size() == 1 + thermalHouses.size() + heatStorages.size() + domesticHotWaterStorages.size() actualAllEntities.contains(thermalBus) actualAllEntities.containsAll(thermalHouses) - actualAllEntities.containsAll(thermalStorages) + actualAllEntities.containsAll(heatStorages) } def "A ThermalGrid's copy method should work as expected"() { given: def thermalBus = Mock(ThermalBusInput) def thermalHouses = [] - def thermalStorages = [] - def thermalGrid = new ThermalGrid(thermalBus, thermalHouses, thermalStorages) + def heatStorages = [] + def domesticHotWaterStorages = [] + def thermalGrid = new ThermalGrid(thermalBus, thermalHouses, heatStorages, domesticHotWaterStorages) def modifiedHouses = [Mock(ThermalHouseInput)] - def modifiedStorages = [Mock(CylindricalStorageInput)] + def modifiedHeatStorages = [Mock(CylindricalStorageInput)] + def modifiedDomesticHotWaterStorages = [Mock(CylindricalStorageInput)] when: def modifiedThermalGrid = thermalGrid.copy() .houses(modifiedHouses as Set) - .storages(modifiedStorages as Set) + .heatStorages(modifiedHeatStorages as Set) + .domesticHotWaterStorages(modifiedDomesticHotWaterStorages as Set) .build() then: modifiedThermalGrid.houses().first() == modifiedHouses.get(0) - modifiedThermalGrid.storages().first() == modifiedStorages.get(0) + modifiedThermalGrid.heatStorages().first() == modifiedHeatStorages.get(0) + modifiedThermalGrid.domesticHotWaterStorages().first() == modifiedDomesticHotWaterStorages.get(0) } } diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInputTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInputTest.groovy new file mode 100644 index 000000000..f28864c13 --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/models/input/thermal/DomesticHotWaterStorageInputTest.groovy @@ -0,0 +1,60 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.datamodel.models.input.thermal + +import edu.ie3.test.common.ThermalUnitInputTestData +import spock.lang.Specification + + +class DomesticHotWaterStorageInputTest extends Specification { + + def "A DomesticHotWaterStorageInput copy method should work as expected"() { + given: + def domesticHotWaterStorageInput = ThermalUnitInputTestData.domesticHotWaterStorageInput + + when: + def alteredUnit = domesticHotWaterStorageInput.copy().storageVolumeLvl(ThermalUnitInputTestData.storageVolumeLvl) + .inletTemp(ThermalUnitInputTestData.inletTemp) + .returnTemp(ThermalUnitInputTestData.returnTemp).c(ThermalUnitInputTestData.c) + .thermalBus(ThermalUnitInputTestData.thermalBus).build() + + + then: + alteredUnit.with { + assert uuid == domesticHotWaterStorageInput.uuid + assert id == domesticHotWaterStorageInput.id + assert operator == domesticHotWaterStorageInput.operator + assert operationTime == domesticHotWaterStorageInput.operationTime + assert thermalBus == domesticHotWaterStorageInput.thermalBus + assert storageVolumeLvl == ThermalUnitInputTestData.storageVolumeLvl + assert inletTemp == ThermalUnitInputTestData.inletTemp + assert returnTemp == ThermalUnitInputTestData.returnTemp + assert c == ThermalUnitInputTestData.c + } + } + + def "Scaling a DomesticHotWaterStorageInput via builder should work as expected"() { + given: + def domesticHotWaterStorageInput = ThermalUnitInputTestData.domesticHotWaterStorageInput + + when: + def alteredUnit = domesticHotWaterStorageInput.copy().scale(2d).build() + + then: + alteredUnit.with { + assert uuid == domesticHotWaterStorageInput.uuid + assert id == domesticHotWaterStorageInput.id + assert operator == domesticHotWaterStorageInput.operator + assert operationTime == domesticHotWaterStorageInput.operationTime + assert thermalBus == domesticHotWaterStorageInput.thermalBus + assert storageVolumeLvl == domesticHotWaterStorageInput.storageVolumeLvl * 2d + assert inletTemp == domesticHotWaterStorageInput.inletTemp + assert returnTemp == domesticHotWaterStorageInput.returnTemp + assert c == domesticHotWaterStorageInput.c + assert pThermalMax == domesticHotWaterStorageInput.pThermalMax * 2d + } + } +} diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy index 0fe0b5bd2..76ccec889 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy @@ -12,6 +12,7 @@ import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import edu.ie3.datamodel.utils.Try import edu.ie3.test.common.SystemParticipantTestData @@ -116,21 +117,41 @@ class ThermalValidationUtilsTest extends Specification { where: invalidCylindricalStorage || expectedSize || expectedException - new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(200, StandardUnits.TEMPERATURE), c, pThermalMax) || 1 || new InvalidEntityException("Inlet temperature of the cylindrical storage cannot be lower or equal than outlet temperature", invalidCylindricalStorage) - new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(100, StandardUnits.TEMPERATURE), c, pThermalMax) || 1 || new InvalidEntityException("Inlet temperature of the cylindrical storage cannot be lower or equal than outlet temperature", invalidCylindricalStorage) - new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, Quantities.getQuantity(-100, StandardUnits.VOLUME), inletTemp, returnTemp, Quantities.getQuantity(-1.05, StandardUnits.SPECIFIC_HEAT_CAPACITY), pThermalMax) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³", invalidCylindricalStorage) + new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(200, StandardUnits.TEMPERATURE), c, Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("Inlet temperature of the cylindrical storage cannot be lower or equal than outlet temperature", invalidCylindricalStorage) + new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(100, StandardUnits.TEMPERATURE), c, Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("Inlet temperature of the cylindrical storage cannot be lower or equal than outlet temperature", invalidCylindricalStorage) + new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, Quantities.getQuantity(-100, StandardUnits.VOLUME), inletTemp, returnTemp, Quantities.getQuantity(-1.05, StandardUnits.SPECIFIC_HEAT_CAPACITY), Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³", invalidCylindricalStorage) new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, Quantities.getQuantity(-100, StandardUnits.VOLUME), inletTemp, returnTemp, Quantities.getQuantity(-1.05, StandardUnits.SPECIFIC_HEAT_CAPACITY), Quantities.getQuantity(-20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³, -20 kW", invalidCylindricalStorage) } + def "ThermalValidationUtils.checkDomesticHotWaterStorage() recognizes all potential errors for a domestic hot water storage"() { + when: + List> exceptions = ThermalValidationUtils.check(invalidDomesticHotWaterStorage).stream().filter { it -> it.failure }.toList() + + then: + exceptions.size() == expectedSize + Exception ex = exceptions.get(0).exception.get() + ex.class == expectedException.class + ex.message == expectedException.message + + where: + invalidDomesticHotWaterStorage || expectedSize || expectedException + new DomesticHotWaterStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(200, StandardUnits.TEMPERATURE), c, Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("Inlet temperature of the domestic hot water storage cannot be lower or equal than outlet temperature", invalidDomesticHotWaterStorage) + new DomesticHotWaterStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(100, StandardUnits.TEMPERATURE), c, Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("Inlet temperature of the domestic hot water storage cannot be lower or equal than outlet temperature", invalidDomesticHotWaterStorage) + new DomesticHotWaterStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, Quantities.getQuantity(-100, StandardUnits.VOLUME), inletTemp, returnTemp, Quantities.getQuantity(-1.05, StandardUnits.SPECIFIC_HEAT_CAPACITY), Quantities.getQuantity(20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³", invalidDomesticHotWaterStorage) + new DomesticHotWaterStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, Quantities.getQuantity(-100, StandardUnits.VOLUME), inletTemp, returnTemp, Quantities.getQuantity(-1.05, StandardUnits.SPECIFIC_HEAT_CAPACITY), Quantities.getQuantity(-20, PowerSystemUnits.KILOWATT)) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³, -20 kW", invalidDomesticHotWaterStorage) + } + def "ThermalValidationUtils.check() works for complete ThermalGrid as well"() { when: def thermalBus = ThermalUnitInputTestData.thermalBus + def domesticHotWaterStorageInput = [ + ThermalUnitInputTestData.domesticHotWaterStorageInput + ] def cylindricalStorageInput = [ ThermalUnitInputTestData.cylindricalStorageInput ] - - ThermalGrid thermalGrid = new ThermalGrid(thermalBus, [thermalHouse], cylindricalStorageInput) + ThermalGrid thermalGrid = new ThermalGrid(thermalBus, [thermalHouse], cylindricalStorageInput, domesticHotWaterStorageInput) List> exceptions = ThermalValidationUtils.check(thermalGrid).stream().filter { it -> it.failure }.toList() @@ -146,4 +167,32 @@ class ThermalValidationUtilsTest extends Specification { thermalHouse || expectedSize || expectedException new ThermalHouseInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, thermalConductance, ethCapa, Quantities.getQuantity(0, StandardUnits.TEMPERATURE), UPPER_TEMPERATURE_LIMIT, LOWER_TEMPERATURE_LIMIT, HOUSING_TYPE, NUMBER_INHABITANTS) || 1 || new InvalidEntityException("Target temperature must be higher than lower temperature limit and lower than upper temperature limit", thermalHouse) } + + def "ThermalValidationUtils.check() works for complete ThermalGrid as well"() { + when: + def thermalBus = ThermalUnitInputTestData.thermalBus + def cylindricalStorageInput = [ + ThermalUnitInputTestData.cylindricalStorageInput + ] + def domesticHotWaterStorageInput = [ + ThermalUnitInputTestData.domesticHotWaterStorageInput + ] + + + ThermalGrid thermalGrid = new ThermalGrid(thermalBus, [thermalHouse], cylindricalStorageInput, domesticHotWaterStorageInput) + + + List> exceptions = ThermalValidationUtils.check(thermalGrid).stream().filter { it -> it.failure }.toList() + + then: + exceptions.size() == expectedSize + Exception ex = exceptions.get(0).exception.get() + ex.class == expectedException.class + ex.message == expectedException.message + + + where: + thermalHouse || expectedSize || expectedException + new ThermalHouseInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, thermalConductance, ethCapa, Quantities.getQuantity(0, StandardUnits.TEMPERATURE), UPPER_TEMPERATURE_LIMIT, LOWER_TEMPERATURE_LIMIT, "house", 2) || 1 || new InvalidEntityException("Target temperature must be higher than lower temperature limit and lower than upper temperature limit", thermalHouse) + } } diff --git a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy index a3dc6a8f9..7611b78bc 100644 --- a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy @@ -173,11 +173,12 @@ class SystemParticipantTestData { public static final ComparableQuantity returnTemp = Quantities.getQuantity(80, TEMPERATURE) public static final ComparableQuantity c = Quantities.getQuantity( 1, SPECIFIC_HEAT_CAPACITY) - public static final ComparableQuantity pThermalMax = Quantities.getQuantity(20, ACTIVE_POWER_IN) + public static final ComparableQuantity pThermalMax = Quantities.getQuantity( + 20, ACTIVE_POWER_IN) public static final ThermalStorageInput thermalStorage = new CylindricalStorageInput( UUID.fromString("8851813b-3a7d-4fee-874b-4df9d724e4b3"), - "test_cylindricThermalStorage", + "test_cylindricalThermalStorage", GridTestData.profBroccoli, OperationTime.notLimited(), thermalBus, @@ -185,7 +186,7 @@ class SystemParticipantTestData { inletTemp, returnTemp, c, - pThermalMax, + pThermalMax ) public static final ChpInput chpInput = new ChpInput( diff --git a/src/test/groovy/edu/ie3/test/common/ThermalUnitInputTestData.groovy b/src/test/groovy/edu/ie3/test/common/ThermalUnitInputTestData.groovy index 393074733..3f6b6c3db 100644 --- a/src/test/groovy/edu/ie3/test/common/ThermalUnitInputTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/ThermalUnitInputTestData.groovy @@ -9,6 +9,7 @@ import edu.ie3.datamodel.models.OperationTime import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput +import edu.ie3.datamodel.models.input.thermal.DomesticHotWaterStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.interfaces.HeatCapacity @@ -72,4 +73,16 @@ class ThermalUnitInputTestData extends SystemParticipantTestData { returnTemp, c, pThermalMax) + + public static final domesticHotWaterStorageInput = new DomesticHotWaterStorageInput( + thermalUnitUuid, + "testDomesticHotWaterStorageInput", + operator, + operationTime, + thermalBus, + storageVolumeLvl, + inletTemp, + returnTemp, + c, + pThermalMax) } diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv index 0b0114091..141286dbb 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv @@ -1,2 +1,2 @@ -uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,storage_volume_lvl_min,p_thermal_max,thermal_bus,em -8851813b-3a7d-4fee-874b-4df9d724e4b3,1.0,test_cylindricThermalStorage,110.0,,,f15105c4-a2de-4ab8-a621-4bc98e372d92,80.0,1.039154027,0.3,20.0,0d95d7f2-49fb-4d49-8636-383a5220384e,977157f4-25e5-4c72-bf34-440edc778792 +uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,p_thermal_max,thermal_bus,em +8851813b-3a7d-4fee-874b-4df9d724e4b3,1.0,test_cylindricalThermalStorage,110.0,,,f15105c4-a2de-4ab8-a621-4bc98e372d92,80.0,1.039154027,20.0,0d95d7f2-49fb-4d49-8636-383a5220384e,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_thermal/cylindrical_storage_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_thermal/cylindrical_storage_input.csv index 4f57d7972..98f6d91e2 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_thermal/cylindrical_storage_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_thermal/cylindrical_storage_input.csv @@ -1,2 +1,2 @@ -uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,storage_volume_lvl_min,thermal_bus,p_thermal_max -8851813b-3a7d-4fee-874b-4df9d724e4b3,1.0,test_cylindricThermalStorage,110.0,,,f15105c4-a2de-4ab8-a621-4bc98e372d92,80.0,1.039154027,0.3,0d95d7f2-49fb-4d49-8636-383a5220384e,20.0 +uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,thermal_bus,p_thermal_max +8851813b-3a7d-4fee-874b-4df9d724e4b3,1.0,test_cylindricalThermalStorage,110.0,,,f15105c4-a2de-4ab8-a621-4bc98e372d92,80.0,1.039154027,0d95d7f2-49fb-4d49-8636-383a5220384e,20.0