diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a5250fcb..37ef1d290 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
- Adding timeseries for voltage values [#1128](https://github.com/ie3-institute/PowerSystemDataModel/issues/1128)
- Added Staudt to list of reviewers [#1190](https://github.com/ie3-institute/PowerSystemDataModel/issues/1190)
+- Extend ValidationUtils for validating ThermalGrids [#1216](https://github.com/ie3-institute/PowerSystemDataModel/issues/1216)
### Fixed
- Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221)
diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java
similarity index 86%
rename from src/main/java/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtils.java
rename to src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java
index 36c89c8a5..15cc20d2f 100644
--- a/src/main/java/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtils.java
+++ b/src/main/java/edu/ie3/datamodel/utils/validation/ThermalValidationUtils.java
@@ -7,6 +7,7 @@
import edu.ie3.datamodel.exceptions.InvalidEntityException;
import edu.ie3.datamodel.exceptions.ValidationException;
+import edu.ie3.datamodel.models.input.container.ThermalGrid;
import edu.ie3.datamodel.models.input.thermal.*;
import edu.ie3.datamodel.utils.Try;
import edu.ie3.datamodel.utils.Try.Failure;
@@ -14,10 +15,10 @@
import java.util.List;
import javax.measure.Quantity;
-public class ThermalUnitValidationUtils extends ValidationUtils {
+public class ThermalValidationUtils extends ValidationUtils {
/** Private Constructor as this class is not meant to be instantiated */
- private ThermalUnitValidationUtils() {
+ private ThermalValidationUtils() {
throw new IllegalStateException("Don't try and instantiate a Utility class.");
}
@@ -57,6 +58,42 @@ private ThermalUnitValidationUtils() {
return exceptions;
}
+ /**
+ * Validates a thermal grid if:
+ *
+ *
+ *
+ * A "distribution" method, that forwards the check request to specific implementations to fulfill
+ * the checking task, based on the class of the given object.
+ *
+ * @param thermalGrid ThermalGrid to validate
+ * @return a list of try objects either containing an {@link ValidationException} or an empty
+ * Success
+ */
+ protected static List> check(ThermalGrid thermalGrid) {
+ Try isNull = checkNonNull(thermalGrid, "a thermal grid");
+
+ if (isNull.isFailure()) {
+ return List.of(isNull);
+ }
+
+ List> exceptions = new ArrayList<>();
+
+ // Validate houses
+ for (ThermalHouseInput house : thermalGrid.houses()) {
+ exceptions.addAll(checkThermalHouse(house));
+ }
+
+ // Validate storages
+ for (ThermalStorageInput storage : thermalGrid.storages()) {
+ exceptions.addAll(check(storage));
+ }
+
+ return exceptions;
+ }
+
/**
* Validates a thermalSinkInput if:
*
diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java
index cc04e8489..80006953b 100644
--- a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java
+++ b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java
@@ -16,6 +16,7 @@
import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput;
import edu.ie3.datamodel.models.input.connector.type.Transformer3WTypeInput;
import edu.ie3.datamodel.models.input.container.GridContainer;
+import edu.ie3.datamodel.models.input.container.ThermalGrid;
import edu.ie3.datamodel.models.input.graphics.GraphicInput;
import edu.ie3.datamodel.models.input.system.SystemParticipantInput;
import edu.ie3.datamodel.models.input.system.type.SystemParticipantTypeInput;
@@ -68,6 +69,8 @@ public static void check(Object obj) throws ValidationException {
exceptions.addAll(GraphicValidationUtils.check((GraphicInput) obj));
} else if (AssetTypeInput.class.isAssignableFrom(obj.getClass())) {
exceptions.addAll(checkAssetType((AssetTypeInput) obj));
+ } else if (ThermalGrid.class.isAssignableFrom(obj.getClass())) {
+ exceptions.addAll(ThermalValidationUtils.check((ThermalGrid) obj));
} else {
logNotImplemented(obj);
}
@@ -151,7 +154,9 @@ else if (SystemParticipantInput.class.isAssignableFrom(assetInput.getClass()))
exceptions.addAll(
SystemParticipantValidationUtils.check((SystemParticipantInput) assetInput));
else if (ThermalUnitInput.class.isAssignableFrom(assetInput.getClass()))
- exceptions.addAll(ThermalUnitValidationUtils.check((ThermalUnitInput) assetInput));
+ exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput));
+ else if (ThermalGrid.class.isAssignableFrom(assetInput.getClass()))
+ exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput));
else {
logNotImplemented(assetInput);
}
diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy
similarity index 79%
rename from src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtilsTest.groovy
rename to src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy
index 61c9bf571..aee73fe73 100644
--- a/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalUnitValidationUtilsTest.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/ThermalValidationUtilsTest.groovy
@@ -10,6 +10,7 @@ import edu.ie3.datamodel.exceptions.ValidationException
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.container.ThermalGrid
import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput
import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput
import edu.ie3.datamodel.utils.Try
@@ -26,7 +27,7 @@ import tech.units.indriya.quantity.Quantities
import javax.measure.quantity.Temperature
import javax.measure.quantity.Volume
-class ThermalUnitValidationUtilsTest extends Specification {
+class ThermalValidationUtilsTest extends Specification {
// General data
private static final UUID thermalUnitUuid = UUID.fromString("717af017-cc69-406f-b452-e022d7fb516a")
@@ -44,7 +45,7 @@ class ThermalUnitValidationUtilsTest extends Specification {
private static final ComparableQuantity UPPER_TEMPERATURE_LIMIT = Quantities.getQuantity(25, StandardUnits.TEMPERATURE)
private static final ComparableQuantity LOWER_TEMPERATURE_LIMIT = Quantities.getQuantity(15, StandardUnits.TEMPERATURE)
- // Specific data for thermal cylindric storage input
+ // Specific data for thermal cylindrical storage input
private static final ComparableQuantity storageVolumeLvl = Quantities.getQuantity(100, StandardUnits.VOLUME)
private static final ComparableQuantity inletTemp = Quantities.getQuantity(100, StandardUnits.TEMPERATURE)
private static final ComparableQuantity returnTemp = Quantities.getQuantity(80, StandardUnits.TEMPERATURE)
@@ -65,7 +66,7 @@ class ThermalUnitValidationUtilsTest extends Specification {
def "ThermalUnitValidationUtils.checkThermalHouse() recognizes all potential errors for a thermal house"() {
when:
- List> exceptions = ThermalUnitValidationUtils.check(invalidThermalHouse).stream().filter { it -> it.failure }.toList()
+ List> exceptions = ThermalValidationUtils.check(invalidThermalHouse).stream().filter { it -> it.failure }.toList()
then:
exceptions.size() == expectedSize
@@ -98,7 +99,7 @@ class ThermalUnitValidationUtilsTest extends Specification {
def "ThermalUnitValidationUtils.checkCylindricalStorage() recognizes all potential errors for a thermal cylindrical storage"() {
when:
- List> exceptions = ThermalUnitValidationUtils.check(invalidCylindricalStorage).stream().filter { it -> it.failure }.toList()
+ List> exceptions = ThermalValidationUtils.check(invalidCylindricalStorage).stream().filter { it -> it.failure }.toList()
then:
exceptions.size() == expectedSize
@@ -107,9 +108,34 @@ class ThermalUnitValidationUtilsTest extends Specification {
ex.message == expectedException.message
where:
- invalidCylindricalStorage || expectedSize || expectedException
- new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(200, StandardUnits.TEMPERATURE), c) || 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) || 1 || new InvalidEntityException("Inlet temperature of the cylindrical storage cannot be lower or equal than outlet temperature", invalidCylindricalStorage)
+ invalidCylindricalStorage || expectedSize || expectedException
+ new CylindricalStorageInput(thermalUnitUuid, id, operator, operationTime, SystemParticipantTestData.thermalBus, storageVolumeLvl, Quantities.getQuantity(100, StandardUnits.TEMPERATURE), Quantities.getQuantity(200, StandardUnits.TEMPERATURE), c) || 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) || 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)) || 1 || new InvalidEntityException("The following quantities have to be positive: -100 ㎥, -1.05 kWh/K*m³", invalidCylindricalStorage)
}
+
+ def "ThermalUnitValidationUtils.check() works for complete ThermalGrid as well"() {
+ when:
+ def thermalBus = ThermalUnitInputTestData.thermalBus
+ def cylindricalStorageInput = [
+ ThermalUnitInputTestData.cylindricStorageInput
+ ]
+
+
+ ThermalGrid thermalGrid = new ThermalGrid(thermalBus, [thermalHouse], cylindricalStorageInput)
+
+
+ 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) || 1 || new InvalidEntityException("Target temperature must be higher than lower temperature limit and lower than upper temperature limit", thermalHouse)
+ }
}